├── .gitignore ├── .htaccess ├── .travis.yml ├── LICENSE ├── README.md ├── app ├── Config │ └── Config.php ├── Controllers │ └── KeyController.php ├── Core │ ├── Auth.php │ ├── Auth │ │ ├── AuthBasic.php │ │ └── AuthInterface.php │ ├── Engine.php │ ├── Exception │ │ ├── InvalidApiKey.php │ │ ├── InvalidAuthException.php │ │ ├── LimitReachedException.php │ │ └── ResourceNotFoundException.php │ ├── Limits │ │ ├── Key.php │ │ └── Method.php │ ├── Response.php │ ├── Security.php │ └── Whitelist.php ├── Models │ ├── ApiKeysModel.php │ ├── ApiLogsModel.php │ └── CommonBehaviour.php └── Transformers │ └── KeyTransformer.php ├── codeception.yml ├── composer.json ├── migrations ├── 20141110142726_api_keys.php └── 20141110145038_api_logs.php ├── phinx.yml ├── public ├── .htaccess ├── bootstrap.php └── index.php └── tests ├── _bootstrap.php ├── _data └── dump.sql ├── _support ├── AcceptanceHelper.php ├── FunctionalHelper.php └── UnitHelper.php ├── acceptance.suite.yml ├── acceptance ├── AcceptanceTester.php └── _bootstrap.php ├── functional.suite.yml ├── functional ├── FunctionalTester.php └── _bootstrap.php ├── phalcon.ini ├── unit.suite.yml └── unit ├── ApiLimitTest.php ├── AuthTest.php ├── UnitTester.php ├── WhitelistTest.php └── _bootstrap.php /.gitignore: -------------------------------------------------------------------------------- 1 | vendor/* 2 | composer.lock 3 | .idea/* 4 | 5 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | 2 | RewriteEngine on 3 | RewriteRule ^$ public/ [L] 4 | RewriteRule (.*) public/$1 [L] 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: php 2 | 3 | php: 4 | - 5.4 5 | - 5.5 6 | 7 | script: 8 | - vendor/bin/codecept build 9 | - vendor/bin/codecept run 10 | 11 | before_script: 12 | - git clone -q https://github.com/phalcon/cphalcon.git 13 | - (cd cphalcon/ext; export CFLAGS="-g3 -O1 -std=gnu90 -Wall -Werror -Wno-error=uninitialized"; phpize && ./configure --silent --enable-phalcon && make --silent -j4 > /dev/null && sudo make --silent install && phpenv config-add ../unit-tests/ci/phalcon.ini) 14 | - wget http://getcomposer.org/composer.phar 15 | - php composer.phar self-update 16 | - php composer.phar install 17 | - php -i | grep phalcon 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Prasetyo Wicaksono 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Phalcon Restful Webservice [![Scrutinizer Code Quality](https://scrutinizer-ci.com/g/Atriedes/phalcon-restful-webservice/badges/quality-score.png?b=master)](https://scrutinizer-ci.com/g/Atriedes/phalcon-restful-webservice/?branch=master) [![Build Status](https://travis-ci.org/Atriedes/phalcon-restful-webservice.svg?branch=master)](https://travis-ci.org/Atriedes/phalcon-restful-webservice) 2 | === 3 | 4 | Just another Phalcon RESTful webservice. It use Phalcon annotation routing for advanced and flexible routing configuration. 5 | 6 | Routing & Options 7 | === 8 | 9 | All routing must be placed in `app/controllers` and must have `Controller` suffix for class name. If your controller name is `Example` then class name is `ExampleController`. You can limit max request to specific API key or method. Limiting max request for API key can be set in Class Annotation, It will limit API key to access all method inside class. Also if you want to limit specific method you can set in Method Annotation, it will limit all API key to accessing this method. 10 | 11 | Class Annotation Options 12 | --- 13 | 14 | `@RoutePrefix("your-prefix-url-here")` - `required` 15 | 16 | `@Api(level=1-10, limits={"key": {"increment": "-1 month", "limit": 1000}})` - `optional` 17 | 18 | Method Annotation Options 19 | --- 20 | 21 | `@Get("/")` - `required` 22 | 23 | `@Post("/")` - `required` 24 | 25 | `@Put("/)` - `required` 26 | 27 | `@Delete("/")` - `required` 28 | 29 | `@Auth("your-auth-driver")` - `optional` 30 | 31 | `@Limit({"increment": "-1 hour", "limit": 50})` - `optional` 32 | 33 | Full Example 34 | --- 35 | 36 | ~~~php 37 | use Phalcon\Mvc\Controller; 38 | 39 | /** 40 | * @RoutePrefix("/v1/example") 41 | * @Api(level=1, 42 | * limits={ 43 | * "key" : { 44 | * "increment" : "-1 day", "limit" : 1000} 45 | * } 46 | * ) 47 | */ 48 | class ExampleController extends Controller 49 | { 50 | /** 51 | * @Get("/") 52 | * @Limit({"increment": "-1 hour", "limit": 50}); 53 | * @Auth("basic") 54 | * @Whitelist() 55 | */ 56 | public function getAction() 57 | { 58 | // Your Logic here 59 | } 60 | 61 | /** 62 | * @Post("/") 63 | * @Limit({"increment": "-1 hour", "limit": 50}); 64 | * @Auth("basic") 65 | */ 66 | public function addAction() 67 | { 68 | // Your Logic here 69 | } 70 | } 71 | ~~~ 72 | 73 | Auth 74 | === 75 | You add additional layer for security by add authentication, Auth can only enabled per class method by add annotation. 76 | 77 | Basic 78 | --- 79 | This is enable HTTP auth basic when user request webservice. 80 | 81 | Response 82 | === 83 | Response are handled by [ellipsesynergie/api-response](https://github.com/ellipsesynergie/api-response) you can access this library via phalcon DI using `apiResponse` 84 | 85 | Usage 86 | --- 87 | 88 | ~~~php 89 | /** 90 | * @Get("/") 91 | * @Limit({"increment": "1 hour", "limit": 50}); 92 | * @Auth("basic") 93 | */ 94 | public function getAction() 95 | { 96 | $this->apiResponse->withArray( 97 | [ 98 | "name" => "Jowy" 99 | ], 100 | [ 101 | "My-Custom-Response-Header" => "It rocks" 102 | ] 103 | ); 104 | } 105 | ~~~ 106 | 107 | Migration 108 | === 109 | 110 | `php vendor/bin/phinx migrate` 111 | 112 | Test 113 | === 114 | 115 | `php vendor/bin/codecept run` 116 | 117 | To do 118 | === 119 | 120 | 1. Improve documentation 121 | 2. **Add IP based whitelist/blacklist (implemented)** 122 | 3. Add IP based limitting 123 | 4. Add dashboard for monitoring webservice 124 | -------------------------------------------------------------------------------- /app/Config/Config.php: -------------------------------------------------------------------------------- 1 | [ 5 | "host" => "localhost", 6 | "username" => "root", 7 | "password" => "123", 8 | "port" => 3306, 9 | "dbname" => "phrest_dev" 10 | ], 11 | "auth" => [ 12 | "username" => "jowy", 13 | "password" => "Blink182" 14 | ], 15 | "whitelist" => [ 16 | "127.0.0.1", 17 | "127.0.0.2" 18 | ] 19 | ]; 20 | 21 | // EOF 22 | -------------------------------------------------------------------------------- /app/Controllers/KeyController.php: -------------------------------------------------------------------------------- 1 | request->getHeader("HTTP_X_API_KEY"); 29 | $api = ApiKeysModel::findFirst("key = '{$apiKey}'"); 30 | return $this->apiResponse->withItem($api, new KeyTransformer()); 31 | } 32 | 33 | /** 34 | * @Put("/") 35 | * @Limit({"increment": "-1 hour", "limit": 50}); 36 | */ 37 | public function editAction() 38 | { 39 | $level = $this->request->getPut("level"); 40 | $ignore_limit = $this->request->getPut("ignore_limit"); 41 | 42 | $apiKey = $this->request->getHeader("HTTP_X_API_KEY"); 43 | $api = ApiKeysModel::findFirst("key = '{$apiKey}'"); 44 | 45 | $api->setLevel(isset($level) ? $level : $api->getLevel()); 46 | $api->setIgnoreLimit(isset($ignore_limit) ? $ignore_limit : $api->getIgnoreLimit()); 47 | 48 | $api->save(); 49 | 50 | return $this->apiResponse->withItem($api, new KeyTransformer()); 51 | } 52 | 53 | /** 54 | * @Post("/") 55 | * @Limit({"increment": "-1 hour", "limit": 50}); 56 | */ 57 | public function addAction() 58 | { 59 | $level = $this->request->getPost("level"); 60 | $ignore_limit = $this->request->getPost("ignore_limit"); 61 | 62 | $api = new ApiKeysModel(); 63 | $api->setKey($this->generateApiKey()); 64 | $api->setIgnoreLimit((isset($ignore_limit) ? $ignore_limit : 0)); 65 | $api->setLevel((isset($level) ? $level : 1)); 66 | 67 | if ($api->save()) { 68 | return $this->apiResponse->withItem($api, new KeyTransformer()); 69 | } else { 70 | return $this->apiResponse->errorInternalError(); 71 | } 72 | 73 | } 74 | 75 | /** 76 | * @Delete("/") 77 | * @Limit({"increment": "-1 hour", "limit": 50}); 78 | */ 79 | public function deleteAction() 80 | { 81 | $key = $this->request->get("key"); 82 | $api = ApiKeysModel::findFirst("key = '{$key}'"); 83 | 84 | if (!$api) { 85 | return $this->apiResponse->errorInternalError(); 86 | } 87 | 88 | if (!$api->delete()) { 89 | return $this->apiResponse->errorInternalError(); 90 | } 91 | 92 | return $this->apiResponse->withArray(["deleted" => true]); 93 | } 94 | 95 | private function generateApiKey() 96 | { 97 | $factory = new \RandomLib\Factory; 98 | $generator = $factory->getGenerator(new \SecurityLib\Strength(\SecurityLib\Strength::MEDIUM)); 99 | 100 | $key = $generator->generateString(32, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"); 101 | while (true) { 102 | $apiKey = ApiKeysModel::findFirst("key = '{$key}'"); 103 | 104 | if (!$apiKey) { 105 | break; 106 | } 107 | 108 | $key = $generator->generateString(32); 109 | } 110 | 111 | return $key; 112 | } 113 | 114 | } 115 | 116 | // EOF 117 | -------------------------------------------------------------------------------- /app/Core/Auth.php: -------------------------------------------------------------------------------- 1 | di->get("config"); 16 | if (isset($_SERVER["PHP_AUTH_USER"])) { 17 | if ($_SERVER["PHP_AUTH_USER"] != $config["auth"]["username"] || 18 | $_SERVER["PHP_AUTH_PW"] != $config["auth"]["password"] 19 | ) { 20 | throw new InvalidAuthException("Not authorized", 401); 21 | } 22 | } else { 23 | throw new InvalidAuthException("Not authorized", 401); 24 | } 25 | 26 | 27 | return true; 28 | } 29 | 30 | public static function get() 31 | { 32 | return new self(); 33 | } 34 | } 35 | 36 | // EOF 37 | -------------------------------------------------------------------------------- /app/Core/Auth/AuthInterface.php: -------------------------------------------------------------------------------- 1 | getLevel() < $api_annotation->getNamedArgument("level")) { 23 | throw new InvalidApiKey("Invalid API key", 403); 24 | } 25 | 26 | return $key; 27 | } 28 | 29 | public function checkAuth($method_annotation) 30 | { 31 | // check if method has auth annotation 32 | if ($method_annotation->has("Auth")) { 33 | $auth = $method_annotation->get("Auth")->getArguments(); 34 | $class = "Jowy\\Phrest\\Core\\Auth\\Auth" . ucfirst($auth[0]); 35 | $class::get()->auth(); 36 | } 37 | } 38 | 39 | public function checkWhitelist($method_annotation) 40 | { 41 | // do whitelist check 42 | ($method_annotation->has("Whitelist")) 43 | ? WhitelistSecurity::get($this->request->getClientAddress())->check() : true; 44 | } 45 | 46 | public function checkKeyLimitOnClass($key, $limit_annotation) 47 | { 48 | // check limit for key to access all resources 49 | Key::get($key, $limit_annotation["key"]["increment"], $limit_annotation["key"]["limit"])->checkLimit(); 50 | } 51 | 52 | public function checkMethodLimitByKey($key, $method_annotation) 53 | { 54 | // check key has exceed to access resource 55 | Method::get( 56 | $key, 57 | $this->request->get("_url"), 58 | $this->request->getMethod(), 59 | $method_annotation[0]["increment"], 60 | $method_annotation[0]["limit"] 61 | )->checkLimit(); 62 | } 63 | 64 | public function log($key_id, $ip_address, $http_method, $route) 65 | { 66 | $params = []; 67 | if ($this->request->isGet() || $this->request->isDelete()) { 68 | $params = $this->request->get(); 69 | } elseif ($this->request->isPost()) { 70 | $params = $this->request->getPost(); 71 | } elseif ($this->request->isPut()) { 72 | $params = $this->request->getPut(); 73 | } 74 | 75 | $logs = new ApiLogsModel(); 76 | $logs->setApiKeyId($key_id); 77 | $logs->setIpAddress($ip_address); 78 | $logs->setMethod($http_method); 79 | $logs->setRoute($route); 80 | $logs->setParam(serialize($params)); 81 | $logs->save(); 82 | } 83 | } 84 | 85 | // EOF 86 | -------------------------------------------------------------------------------- /app/Core/Exception/InvalidApiKey.php: -------------------------------------------------------------------------------- 1 | key = $key; 21 | $this->increment = $increment; 22 | $this->limit = $limit; 23 | } 24 | 25 | public function checkLimit() 26 | { 27 | if (!$this->increment == 0 && !$this->limit == 0) { 28 | $date = date("Y-m-d H:i:s", strtotime($this->increment)); 29 | 30 | $logs = $this->key->getApiLogs("created_at > '{$date}'"); 31 | 32 | if (count($logs) >= $this->limit) { 33 | throw new LimitReachedException("Limit reached", 503); 34 | } 35 | 36 | return true; 37 | } 38 | } 39 | 40 | public static function get($key, $increment = "-1 day", $limit = 10000) 41 | { 42 | return new self($key, $increment, $limit); 43 | } 44 | } 45 | 46 | // EOF 47 | -------------------------------------------------------------------------------- /app/Core/Limits/Method.php: -------------------------------------------------------------------------------- 1 | key = $key; 25 | $this->uri = $uri; 26 | $this->http_method = $http_method; 27 | $this->increment = $increment; 28 | $this->limit = $limit; 29 | } 30 | 31 | public function checkLimit() 32 | { 33 | if (!$this->increment == 0 && !$this->limit == 0) { 34 | $date = date("Y-m-d H:i:s", strtotime($this->increment)); 35 | 36 | $logs = $this->key->getApiLogs( 37 | "created_at > '{$date}' AND method = '{$this->http_method}' AND route = '{$this->uri}'" 38 | ); 39 | 40 | $count = count($logs); 41 | 42 | if ($count >= $this->limit) { 43 | throw new LimitReachedException("Limit reached", 503); 44 | } 45 | return true; 46 | } 47 | } 48 | 49 | public static function get($key, $uri, $http_method, $increment = "-1 hour", $limit = 1000) 50 | { 51 | return new self($key, $uri, $http_method, $increment, $limit); 52 | } 53 | } 54 | 55 | // EOF 56 | -------------------------------------------------------------------------------- /app/Core/Response.php: -------------------------------------------------------------------------------- 1 | phalconResponse->setJsonContent($array, JSON_NUMERIC_CHECK); 16 | 17 | if ($this->getStatusCode() != 200) { 18 | $this->phalconResponse->setStatusCode($this->getStatusCode(), $array["error"]["message"]); 19 | } else { 20 | $this->phalconResponse->setStatusCode($this->getStatusCode(), "OK"); 21 | } 22 | 23 | 24 | if (isset($headers)) { 25 | foreach ($headers as $key => $value) { 26 | $this->phalconResponse->setHeader($key, $value); 27 | } 28 | } 29 | $this->phalconResponse->setContentType('application/json'); 30 | 31 | return $this->phalconResponse->send(); 32 | } 33 | 34 | public function setPhalconResponse(ResponseInterface $phalconResponse) 35 | { 36 | $this->phalconResponse = $phalconResponse; 37 | } 38 | } 39 | 40 | // EOF 41 | -------------------------------------------------------------------------------- /app/Core/Security.php: -------------------------------------------------------------------------------- 1 | annotations->get($dispatcher->getHandlerClass())->getClassAnnotations(); 20 | $api_annotation = $class_annotation->get("Api"); 21 | 22 | // read method annotation 23 | $method_annotation = $this->annotations->getMethod( 24 | $dispatcher->getHandlerClass(), 25 | $dispatcher->getActiveMethod() 26 | ); 27 | 28 | $engine = new SecurityEngine(); 29 | 30 | // check API key 31 | $key = $engine->checkKeyLevel($this->request->getHeader("HTTP_X_API_KEY"), $api_annotation); 32 | 33 | // check authentication if exist 34 | $engine->checkAuth($method_annotation); 35 | 36 | // check IP whitelist 37 | $engine->checkWhitelist($method_annotation); 38 | 39 | $hasLimit = $api_annotation->hasNamedArgument("limits") || $method_annotation->has("Limit"); 40 | 41 | // check limit 42 | if (!$key->getIgnoreLimit() && $hasLimit) { 43 | $engine->checkKeyLimitOnClass($key, $api_annotation->getNamedArgument("limits")); 44 | $engine->checkMethodLimitByKey($key, $method_annotation->get("Limit")->getArguments()); 45 | } 46 | 47 | // write logs to db 48 | $engine->log( 49 | $key->getApiKeyId(), 50 | $this->request->getClientAddress(), 51 | $this->request->getMethod(), 52 | $this->request->get("_url") 53 | ); 54 | 55 | } catch (PhalconException $e) { 56 | $this->apiResponse->withError($e->getMessage(), $e->getCode()); 57 | return false; 58 | } 59 | 60 | return true; 61 | } 62 | } 63 | 64 | // EOF 65 | -------------------------------------------------------------------------------- /app/Core/Whitelist.php: -------------------------------------------------------------------------------- 1 | ip = $ip; 17 | } 18 | 19 | public function check() 20 | { 21 | $config = $this->di->get("config"); 22 | 23 | if (!in_array($this->ip, (array)$config["whitelist"])) { 24 | throw new InvalidAuthException("Unauthorized", 401); 25 | } 26 | 27 | return true; 28 | } 29 | 30 | public static function get($ip) 31 | { 32 | return new self($ip); 33 | } 34 | } 35 | 36 | // EOF 37 | -------------------------------------------------------------------------------- /app/Models/ApiKeysModel.php: -------------------------------------------------------------------------------- 1 | setSource("api_keys"); 29 | $this->hasMany( 30 | "api_key_id", 31 | "Jowy\\Phrest\\Models\\ApiLogsModel", 32 | "api_key_id", 33 | [ 34 | "alias" => "ApiLogs" 35 | ] 36 | ); 37 | } 38 | 39 | /** 40 | * @param mixed $api_key_id 41 | */ 42 | public function setApiKeyId($api_key_id) 43 | { 44 | $this->api_key_id = $api_key_id; 45 | } 46 | 47 | /** 48 | * @return mixed 49 | */ 50 | public function getApiKeyId() 51 | { 52 | return $this->api_key_id; 53 | } 54 | 55 | /** 56 | * @param mixed $ignore_limit 57 | */ 58 | public function setIgnoreLimit($ignore_limit) 59 | { 60 | $this->ignore_limit = $ignore_limit; 61 | } 62 | 63 | /** 64 | * @return mixed 65 | */ 66 | public function getIgnoreLimit() 67 | { 68 | return $this->ignore_limit; 69 | } 70 | 71 | /** 72 | * @param mixed $key 73 | */ 74 | public function setKey($key) 75 | { 76 | $this->key = $key; 77 | } 78 | 79 | /** 80 | * @return mixed 81 | */ 82 | public function getKey() 83 | { 84 | return $this->key; 85 | } 86 | 87 | /** 88 | * @param mixed $level 89 | */ 90 | public function setLevel($level) 91 | { 92 | $this->level = $level; 93 | } 94 | 95 | /** 96 | * @return mixed 97 | */ 98 | public function getLevel() 99 | { 100 | return $this->level; 101 | } 102 | 103 | /** 104 | * @return mixed 105 | */ 106 | public function getCreatedAt() 107 | { 108 | return $this->created_at; 109 | } 110 | 111 | /** 112 | * @return mixed 113 | */ 114 | public function getUpdatedAt() 115 | { 116 | return $this->updated_at; 117 | } 118 | } 119 | 120 | // EOF 121 | -------------------------------------------------------------------------------- /app/Models/ApiLogsModel.php: -------------------------------------------------------------------------------- 1 | setSource("api_logs"); 32 | $this->belongsTo("api_key_id", "Jowy\\Phrest\\Models\\ApiKeysModel", "api_key_id"); 33 | } 34 | 35 | /** 36 | * @param mixed $api_key_id 37 | */ 38 | public function setApiKeyId($api_key_id) 39 | { 40 | $this->api_key_id = $api_key_id; 41 | } 42 | 43 | /** 44 | * @return mixed 45 | */ 46 | public function getApiKeyId() 47 | { 48 | return $this->api_key_id; 49 | } 50 | 51 | /** 52 | * @param mixed $api_log_id 53 | */ 54 | public function setApiLogId($api_log_id) 55 | { 56 | $this->api_log_id = $api_log_id; 57 | } 58 | 59 | /** 60 | * @return mixed 61 | */ 62 | public function getApiLogId() 63 | { 64 | return $this->api_log_id; 65 | } 66 | 67 | /** 68 | * @param mixed $ip_address 69 | */ 70 | public function setIpAddress($ip_address) 71 | { 72 | $this->ip_address = $ip_address; 73 | } 74 | 75 | /** 76 | * @return mixed 77 | */ 78 | public function getIpAddress() 79 | { 80 | return $this->ip_address; 81 | } 82 | 83 | /** 84 | * @param mixed $method 85 | */ 86 | public function setMethod($method) 87 | { 88 | $this->method = $method; 89 | } 90 | 91 | /** 92 | * @return mixed 93 | */ 94 | public function getMethod() 95 | { 96 | return $this->method; 97 | } 98 | 99 | /** 100 | * @param mixed $param 101 | */ 102 | public function setParam($param) 103 | { 104 | $this->param = $param; 105 | } 106 | 107 | /** 108 | * @return mixed 109 | */ 110 | public function getParam() 111 | { 112 | return $this->param; 113 | } 114 | 115 | /** 116 | * @param mixed $route 117 | */ 118 | public function setRoute($route) 119 | { 120 | $this->route = $route; 121 | } 122 | 123 | /** 124 | * @return mixed 125 | */ 126 | public function getRoute() 127 | { 128 | return $this->route; 129 | } 130 | 131 | /** 132 | * @return mixed 133 | */ 134 | public function getCreatedAt() 135 | { 136 | return $this->created_at; 137 | } 138 | 139 | /** 140 | * @return mixed 141 | */ 142 | public function getUpdatedAt() 143 | { 144 | return $this->updated_at; 145 | } 146 | } 147 | 148 | // EOF 149 | -------------------------------------------------------------------------------- /app/Models/CommonBehaviour.php: -------------------------------------------------------------------------------- 1 | created_at = date("Y-m-d H:i:s"); 12 | } 13 | 14 | public function beforeUpdate() 15 | { 16 | $this->updated_at = date("Y-m-d H:i:s"); 17 | } 18 | } 19 | 20 | //EOF 21 | -------------------------------------------------------------------------------- /app/Transformers/KeyTransformer.php: -------------------------------------------------------------------------------- 1 | (int)$data->getApiKeyId(), 15 | "key" => $data->getKey(), 16 | "level" => $data->getLevel(), 17 | "ignore_limit" => $data->getIgnoreLimit(), 18 | "created_at" => [ 19 | "date" => $data->getCreatedAt(), 20 | "timezone" => date_default_timezone_get() 21 | ], 22 | "updated_at" => [ 23 | "date" => $data->getUpdatedAt(), 24 | "timezone" => date_default_timezone_get() 25 | ] 26 | ]; 27 | } 28 | } 29 | 30 | // EOF 31 | -------------------------------------------------------------------------------- /codeception.yml: -------------------------------------------------------------------------------- 1 | actor: Tester 2 | paths: 3 | tests: tests 4 | log: tests/_output 5 | data: tests/_data 6 | helpers: tests/_support 7 | settings: 8 | bootstrap: _bootstrap.php 9 | colors: true 10 | memory_limit: 1024M 11 | modules: 12 | config: 13 | Db: 14 | dsn: 'mysql:host=localhost;dbname=phrest_dev' 15 | user: 'root' 16 | password: '123' 17 | dump: tests/_data/dump.sql 18 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "jowy/phalcon-restful-webservice", 3 | "description": "Phalcon RESTful Webservice", 4 | "minimum-stability": "stable", 5 | "license": "MIT", 6 | "authors": [ 7 | { 8 | "name": "Prasetyo Wicaksono", 9 | "email": "prasetyo@nanomit.es" 10 | } 11 | ], 12 | "require": { 13 | "ellipsesynergie/api-response": "0.7.0", 14 | "codeception/codeception": "*", 15 | "robmorgan/phinx": "*", 16 | "codeception/mockery-module": "~0.2", 17 | "ircmaxell/random-lib": "~1.0" 18 | }, 19 | "autoload": { 20 | "psr-4": { 21 | "Jowy\\Phrest\\": "app/" 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /migrations/20141110142726_api_keys.php: -------------------------------------------------------------------------------- 1 | hasTable("api_keys")) { 26 | $apiKeys = $this->table( 27 | "api_keys", 28 | [ 29 | "id" => "api_key_id", 30 | "primary_key" => [ 31 | "api_key_id" 32 | ] 33 | ] 34 | ); 35 | 36 | $apiKeys->addColumn("key", "string", ["length" => 64]) 37 | ->addColumn("level", "integer", ["default" => 1]) 38 | ->addColumn("ignore_limit", "boolean", ["default" => 0]) 39 | ->addColumn("created_at", "datetime", ["null" => true]) 40 | ->addColumn("updated_at", "datetime", ["null" => true]) 41 | ->addIndex(["key"], ["unique" => true]) 42 | ->create(); 43 | } 44 | 45 | } 46 | 47 | /** 48 | * Migrate Down. 49 | */ 50 | public function down() 51 | { 52 | $this->dropTable("api_keys"); 53 | } 54 | } 55 | 56 | //EOF 57 | -------------------------------------------------------------------------------- /migrations/20141110145038_api_logs.php: -------------------------------------------------------------------------------- 1 | hasTable("api_logs")) { 26 | $apiLogs = $this->table( 27 | "api_logs", 28 | [ 29 | "id" => "api_logs_id", 30 | "primary_key" => [ 31 | "api_logs_id" 32 | ] 33 | ] 34 | ); 35 | 36 | $apiLogs->addColumn("api_key_id", "integer") 37 | ->addColumn("route", "string", ["length" => 128]) 38 | ->addColumn("method", "string", ["length" => 64]) 39 | ->addColumn("param", "text", ["null" => true]) 40 | ->addColumn("ip_address", "string", ["length" => 64]) 41 | ->addColumn("created_at", "datetime", ["null" => true]) 42 | ->addColumn("updated_at", "datetime", ["null" => true]) 43 | ->addForeignKey("api_key_id", "api_keys", "api_key_id", ["delete" => "CASCADE"]) 44 | ->addIndex(["created_at", "updated_at"]) 45 | ->create(); 46 | } 47 | 48 | } 49 | 50 | /** 51 | * Migrate Down. 52 | */ 53 | public function down() 54 | { 55 | $this->dropTable("api_logs"); 56 | } 57 | } 58 | 59 | //EOF 60 | -------------------------------------------------------------------------------- /phinx.yml: -------------------------------------------------------------------------------- 1 | paths: 2 | migrations: %%PHINX_CONFIG_DIR%%/migrations 3 | 4 | environments: 5 | default_migration_table: phinxlog 6 | default_database: development 7 | production: 8 | adapter: mysql 9 | host: localhost 10 | name: production_db 11 | user: root 12 | pass: '' 13 | port: 3306 14 | charset: utf8 15 | 16 | development: 17 | adapter: mysql 18 | host: localhost 19 | name: phrest_dev 20 | user: root 21 | pass: '123' 22 | port: 3306 23 | charset: utf8 24 | 25 | testing: 26 | adapter: mysql 27 | host: localhost 28 | name: testing_db 29 | user: root 30 | pass: '' 31 | port: 3306 32 | charset: utf8 33 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | 2 | RewriteEngine On 3 | RewriteCond %{REQUEST_FILENAME} !-d 4 | RewriteCond %{REQUEST_FILENAME} !-f 5 | RewriteCond %{REQUEST_FILENAME} !favicon.ico 6 | RewriteRule ^(.*)$ index.php?_url=/$1 [QSA,L] 7 | 8 | -------------------------------------------------------------------------------- /public/bootstrap.php: -------------------------------------------------------------------------------- 1 | registerNamespaces( 6 | [ 7 | "Jowy\\Phrest" => __DIR__ . "/../app" 8 | ], 9 | true 10 | )->register(); 11 | 12 | $di = new \Phalcon\DI\FactoryDefault(); 13 | 14 | $di->setShared( 15 | "config", 16 | function () { 17 | require __DIR__ . "/../app/Config/Config.php"; 18 | return new \Phalcon\Config($config); 19 | } 20 | ); 21 | 22 | $di->setShared( 23 | "db", 24 | function () use ($di) { 25 | return new \Phalcon\Db\Adapter\Pdo\Mysql( 26 | [ 27 | "host" => $di["config"]->database->host, 28 | "username" => $di["config"]->database->username, 29 | "password" => $di["config"]->database->password, 30 | "port" => $di["config"]->database->port, 31 | "dbname" => $di["config"]->database->dbname 32 | ] 33 | ); 34 | } 35 | ); 36 | 37 | $di->setShared( 38 | "apiResponse", 39 | function () { 40 | $response = new \Jowy\Phrest\Core\Response(new \League\Fractal\Manager()); 41 | $response->setPhalconResponse(new \Phalcon\Http\Response()); 42 | return $response; 43 | } 44 | ); 45 | 46 | $di->set( 47 | "router", 48 | function () { 49 | $router = new \Phalcon\Mvc\Router\Annotations(false); 50 | 51 | $files = array_diff(scandir(__DIR__ . "/../app/Controllers/"), array('..', '.')); 52 | 53 | foreach ($files as $file) { 54 | $file = array_slice(preg_split('/(?=[A-Z])/', $file), 1); 55 | $router->addResource("Jowy\\Phrest\\Controllers\\" . $file[0]); 56 | } 57 | 58 | return $router; 59 | } 60 | ); 61 | 62 | $di->set( 63 | "view", 64 | function () { 65 | $view = new \Phalcon\Mvc\View(); 66 | 67 | $view->disable(); 68 | 69 | return $view; 70 | } 71 | ); 72 | 73 | $di->setShared( 74 | "dispatcher", 75 | function () use ($di) { 76 | $eventsManager = $di->getShared('eventsManager'); 77 | $security = new \Jowy\Phrest\Core\Security($di); 78 | 79 | $eventsManager->attach("dispatch", $security, 2); 80 | 81 | $dispatcher = new \Phalcon\Mvc\Dispatcher(); 82 | 83 | $dispatcher->setEventsManager($eventsManager); 84 | 85 | return $dispatcher; 86 | 87 | } 88 | ); 89 | 90 | $di->setShared( 91 | "security", 92 | function () { 93 | $security = new \Phalcon\Security(); 94 | 95 | $security->setWorkFactor(12); 96 | 97 | return $security; 98 | } 99 | ); 100 | 101 | \Phalcon\DI::setDefault($di); 102 | -------------------------------------------------------------------------------- /public/index.php: -------------------------------------------------------------------------------- 1 | handle()->getContent(); 13 | } catch (\Exception $e) { 14 | $di["apiResponse"]->errorUnauthorized(); 15 | } 16 | // EOF 17 | -------------------------------------------------------------------------------- /tests/_bootstrap.php: -------------------------------------------------------------------------------- 1 | scenario->runStep(new \Codeception\Step\Action('setHeader', func_get_args())); 35 | } 36 | 37 | 38 | /** 39 | * [!] Method is generated. Documentation taken from corresponding module. 40 | * 41 | * Authenticates user for HTTP_AUTH 42 | * 43 | * @param $username 44 | * @param $password 45 | * @see \Codeception\Module\PhpBrowser::amHttpAuthenticated() 46 | */ 47 | public function amHttpAuthenticated($username, $password) { 48 | return $this->scenario->runStep(new \Codeception\Step\Condition('amHttpAuthenticated', func_get_args())); 49 | } 50 | 51 | 52 | /** 53 | * [!] Method is generated. Documentation taken from corresponding module. 54 | * 55 | * Open web page at absolute URL. 56 | * Base url will be reconfigured to use the host of provided Url. 57 | * 58 | * ``` php 59 | * amOnUrl('http://codeception.com'); 61 | * $I->amOnPage('/quickstart'); // moves to http://codeception.com/quickstart 62 | * ?> 63 | * ``` 64 | * @see \Codeception\Module\PhpBrowser::amOnUrl() 65 | */ 66 | public function amOnUrl($url) { 67 | return $this->scenario->runStep(new \Codeception\Step\Condition('amOnUrl', func_get_args())); 68 | } 69 | 70 | 71 | /** 72 | * [!] Method is generated. Documentation taken from corresponding module. 73 | * 74 | * Sets 'url' configuration parameter to hosts subdomain. 75 | * It does not open a page on subdomain. Use `amOnPage` for that 76 | * 77 | * ``` php 78 | * amOnSubdomain('user'); 84 | * $I->amOnPage('/'); 85 | * // moves to http://user.mysite.com/ 86 | * ?> 87 | * ``` 88 | * 89 | * @param $subdomain 90 | * 91 | * @return mixed 92 | * @see \Codeception\Module\PhpBrowser::amOnSubdomain() 93 | */ 94 | public function amOnSubdomain($subdomain) { 95 | return $this->scenario->runStep(new \Codeception\Step\Condition('amOnSubdomain', func_get_args())); 96 | } 97 | 98 | 99 | /** 100 | * [!] Method is generated. Documentation taken from corresponding module. 101 | * 102 | * Low-level API method. 103 | * If Codeception commands are not enough, use [Guzzle HTTP Client](http://guzzlephp.org/) methods directly 104 | * 105 | * Example: 106 | * 107 | * ``` php 108 | * executeInGuzzle(function (\GuzzleHttp\Client $client) { 110 | * $client->get('/get', ['query' => ['foo' => 'bar']]); 111 | * }); 112 | * ?> 113 | * ``` 114 | * 115 | * It is not recommended to use this command on a regular basis. 116 | * If Codeception lacks important Guzzle Client methods, implement them and submit patches. 117 | * 118 | * @param callable $function 119 | * @see \Codeception\Module\PhpBrowser::executeInGuzzle() 120 | */ 121 | public function executeInGuzzle($function) { 122 | return $this->scenario->runStep(new \Codeception\Step\Action('executeInGuzzle', func_get_args())); 123 | } 124 | 125 | 126 | /** 127 | * [!] Method is generated. Documentation taken from corresponding module. 128 | * 129 | * Opens the page. 130 | * Requires relative uri as parameter 131 | * 132 | * Example: 133 | * 134 | * ``` php 135 | * amOnPage('/'); 138 | * // opens /register page 139 | * $I->amOnPage('/register'); 140 | * ?> 141 | * ``` 142 | * 143 | * @param $page 144 | * @see \Codeception\Lib\InnerBrowser::amOnPage() 145 | */ 146 | public function amOnPage($page) { 147 | return $this->scenario->runStep(new \Codeception\Step\Condition('amOnPage', func_get_args())); 148 | } 149 | 150 | 151 | /** 152 | * [!] Method is generated. Documentation taken from corresponding module. 153 | * 154 | * Perform a click on link or button. 155 | * Link or button are found by their names or CSS selector. 156 | * Submits a form if button is a submit type. 157 | * 158 | * If link is an image it's found by alt attribute value of image. 159 | * If button is image button is found by it's value 160 | * If link or button can't be found by name they are searched by CSS selector. 161 | * 162 | * The second parameter is a context: CSS or XPath locator to narrow the search. 163 | * 164 | * Examples: 165 | * 166 | * ``` php 167 | * click('Logout'); 170 | * // button of form 171 | * $I->click('Submit'); 172 | * // CSS button 173 | * $I->click('#form input[type=submit]'); 174 | * // XPath 175 | * $I->click('//form/*[@type=submit]'); 176 | * // link in context 177 | * $I->click('Logout', '#nav'); 178 | * // using strict locator 179 | * $I->click(['link' => 'Login']); 180 | * ?> 181 | * ``` 182 | * 183 | * @param $link 184 | * @param $context 185 | * @see \Codeception\Lib\InnerBrowser::click() 186 | */ 187 | public function click($link, $context = null) { 188 | return $this->scenario->runStep(new \Codeception\Step\Action('click', func_get_args())); 189 | } 190 | 191 | 192 | /** 193 | * [!] Method is generated. Documentation taken from corresponding module. 194 | * 195 | * Check if current page contains the text specified. 196 | * Specify the css selector to match only specific region. 197 | * 198 | * Examples: 199 | * 200 | * ``` php 201 | * see('Logout'); // I can suppose user is logged in 203 | * $I->see('Sign Up','h1'); // I can suppose it's a signup page 204 | * $I->see('Sign Up','//body/h1'); // with XPath 205 | * ?> 206 | * ``` 207 | * 208 | * @param $text 209 | * @param null $selector 210 | * Conditional Assertion: Test won't be stopped on fail 211 | * @see \Codeception\Lib\InnerBrowser::see() 212 | */ 213 | public function canSee($text, $selector = null) { 214 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('see', func_get_args())); 215 | } 216 | /** 217 | * [!] Method is generated. Documentation taken from corresponding module. 218 | * 219 | * Check if current page contains the text specified. 220 | * Specify the css selector to match only specific region. 221 | * 222 | * Examples: 223 | * 224 | * ``` php 225 | * see('Logout'); // I can suppose user is logged in 227 | * $I->see('Sign Up','h1'); // I can suppose it's a signup page 228 | * $I->see('Sign Up','//body/h1'); // with XPath 229 | * ?> 230 | * ``` 231 | * 232 | * @param $text 233 | * @param null $selector 234 | * @see \Codeception\Lib\InnerBrowser::see() 235 | */ 236 | public function see($text, $selector = null) { 237 | return $this->scenario->runStep(new \Codeception\Step\Assertion('see', func_get_args())); 238 | } 239 | 240 | 241 | /** 242 | * [!] Method is generated. Documentation taken from corresponding module. 243 | * 244 | * Check if current page doesn't contain the text specified. 245 | * Specify the css selector to match only specific region. 246 | * 247 | * Examples: 248 | * 249 | * ```php 250 | * dontSee('Login'); // I can suppose user is already logged in 252 | * $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page 253 | * $I->dontSee('Sign Up','//body/h1'); // with XPath 254 | * ?> 255 | * ``` 256 | * 257 | * @param $text 258 | * @param null $selector 259 | * Conditional Assertion: Test won't be stopped on fail 260 | * @see \Codeception\Lib\InnerBrowser::dontSee() 261 | */ 262 | public function cantSee($text, $selector = null) { 263 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSee', func_get_args())); 264 | } 265 | /** 266 | * [!] Method is generated. Documentation taken from corresponding module. 267 | * 268 | * Check if current page doesn't contain the text specified. 269 | * Specify the css selector to match only specific region. 270 | * 271 | * Examples: 272 | * 273 | * ```php 274 | * dontSee('Login'); // I can suppose user is already logged in 276 | * $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page 277 | * $I->dontSee('Sign Up','//body/h1'); // with XPath 278 | * ?> 279 | * ``` 280 | * 281 | * @param $text 282 | * @param null $selector 283 | * @see \Codeception\Lib\InnerBrowser::dontSee() 284 | */ 285 | public function dontSee($text, $selector = null) { 286 | return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSee', func_get_args())); 287 | } 288 | 289 | 290 | /** 291 | * [!] Method is generated. Documentation taken from corresponding module. 292 | * 293 | * Checks if there is a link with text specified. 294 | * Specify url to match link with exact this url. 295 | * 296 | * Examples: 297 | * 298 | * ``` php 299 | * seeLink('Logout'); // matches Logout 301 | * $I->seeLink('Logout','/logout'); // matches Logout 302 | * ?> 303 | * ``` 304 | * 305 | * @param $text 306 | * @param null $url 307 | * Conditional Assertion: Test won't be stopped on fail 308 | * @see \Codeception\Lib\InnerBrowser::seeLink() 309 | */ 310 | public function canSeeLink($text, $url = null) { 311 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeLink', func_get_args())); 312 | } 313 | /** 314 | * [!] Method is generated. Documentation taken from corresponding module. 315 | * 316 | * Checks if there is a link with text specified. 317 | * Specify url to match link with exact this url. 318 | * 319 | * Examples: 320 | * 321 | * ``` php 322 | * seeLink('Logout'); // matches Logout 324 | * $I->seeLink('Logout','/logout'); // matches Logout 325 | * ?> 326 | * ``` 327 | * 328 | * @param $text 329 | * @param null $url 330 | * @see \Codeception\Lib\InnerBrowser::seeLink() 331 | */ 332 | public function seeLink($text, $url = null) { 333 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeLink', func_get_args())); 334 | } 335 | 336 | 337 | /** 338 | * [!] Method is generated. Documentation taken from corresponding module. 339 | * 340 | * Checks if page doesn't contain the link with text specified. 341 | * Specify url to narrow the results. 342 | * 343 | * Examples: 344 | * 345 | * ``` php 346 | * dontSeeLink('Logout'); // I suppose user is not logged in 348 | * ?> 349 | * ``` 350 | * 351 | * @param $text 352 | * @param null $url 353 | * Conditional Assertion: Test won't be stopped on fail 354 | * @see \Codeception\Lib\InnerBrowser::dontSeeLink() 355 | */ 356 | public function cantSeeLink($text, $url = null) { 357 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeLink', func_get_args())); 358 | } 359 | /** 360 | * [!] Method is generated. Documentation taken from corresponding module. 361 | * 362 | * Checks if page doesn't contain the link with text specified. 363 | * Specify url to narrow the results. 364 | * 365 | * Examples: 366 | * 367 | * ``` php 368 | * dontSeeLink('Logout'); // I suppose user is not logged in 370 | * ?> 371 | * ``` 372 | * 373 | * @param $text 374 | * @param null $url 375 | * @see \Codeception\Lib\InnerBrowser::dontSeeLink() 376 | */ 377 | public function dontSeeLink($text, $url = null) { 378 | return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSeeLink', func_get_args())); 379 | } 380 | 381 | 382 | /** 383 | * [!] Method is generated. Documentation taken from corresponding module. 384 | * 385 | * Checks that current uri contains a value 386 | * 387 | * ``` php 388 | * seeInCurrentUrl('home'); 391 | * // to match: /users/1 392 | * $I->seeInCurrentUrl('/users/'); 393 | * ?> 394 | * ``` 395 | * 396 | * @param $uri 397 | * Conditional Assertion: Test won't be stopped on fail 398 | * @see \Codeception\Lib\InnerBrowser::seeInCurrentUrl() 399 | */ 400 | public function canSeeInCurrentUrl($uri) { 401 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeInCurrentUrl', func_get_args())); 402 | } 403 | /** 404 | * [!] Method is generated. Documentation taken from corresponding module. 405 | * 406 | * Checks that current uri contains a value 407 | * 408 | * ``` php 409 | * seeInCurrentUrl('home'); 412 | * // to match: /users/1 413 | * $I->seeInCurrentUrl('/users/'); 414 | * ?> 415 | * ``` 416 | * 417 | * @param $uri 418 | * @see \Codeception\Lib\InnerBrowser::seeInCurrentUrl() 419 | */ 420 | public function seeInCurrentUrl($uri) { 421 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeInCurrentUrl', func_get_args())); 422 | } 423 | 424 | 425 | /** 426 | * [!] Method is generated. Documentation taken from corresponding module. 427 | * 428 | * Checks that current uri does not contain a value 429 | * 430 | * ``` php 431 | * dontSeeInCurrentUrl('/users/'); 433 | * ?> 434 | * ``` 435 | * 436 | * @param $uri 437 | * Conditional Assertion: Test won't be stopped on fail 438 | * @see \Codeception\Lib\InnerBrowser::dontSeeInCurrentUrl() 439 | */ 440 | public function cantSeeInCurrentUrl($uri) { 441 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInCurrentUrl', func_get_args())); 442 | } 443 | /** 444 | * [!] Method is generated. Documentation taken from corresponding module. 445 | * 446 | * Checks that current uri does not contain a value 447 | * 448 | * ``` php 449 | * dontSeeInCurrentUrl('/users/'); 451 | * ?> 452 | * ``` 453 | * 454 | * @param $uri 455 | * @see \Codeception\Lib\InnerBrowser::dontSeeInCurrentUrl() 456 | */ 457 | public function dontSeeInCurrentUrl($uri) { 458 | return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSeeInCurrentUrl', func_get_args())); 459 | } 460 | 461 | 462 | /** 463 | * [!] Method is generated. Documentation taken from corresponding module. 464 | * 465 | * Checks that current url is equal to value. 466 | * Unlike `seeInCurrentUrl` performs a strict check. 467 | * 468 | * ``` php 469 | * seeCurrentUrlEquals('/'); 472 | * ?> 473 | * ``` 474 | * 475 | * @param $uri 476 | * Conditional Assertion: Test won't be stopped on fail 477 | * @see \Codeception\Lib\InnerBrowser::seeCurrentUrlEquals() 478 | */ 479 | public function canSeeCurrentUrlEquals($uri) { 480 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeCurrentUrlEquals', func_get_args())); 481 | } 482 | /** 483 | * [!] Method is generated. Documentation taken from corresponding module. 484 | * 485 | * Checks that current url is equal to value. 486 | * Unlike `seeInCurrentUrl` performs a strict check. 487 | * 488 | * ``` php 489 | * seeCurrentUrlEquals('/'); 492 | * ?> 493 | * ``` 494 | * 495 | * @param $uri 496 | * @see \Codeception\Lib\InnerBrowser::seeCurrentUrlEquals() 497 | */ 498 | public function seeCurrentUrlEquals($uri) { 499 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeCurrentUrlEquals', func_get_args())); 500 | } 501 | 502 | 503 | /** 504 | * [!] Method is generated. Documentation taken from corresponding module. 505 | * 506 | * Checks that current url is not equal to value. 507 | * Unlike `dontSeeInCurrentUrl` performs a strict check. 508 | * 509 | * ``` php 510 | * dontSeeCurrentUrlEquals('/'); 513 | * ?> 514 | * ``` 515 | * 516 | * @param $uri 517 | * Conditional Assertion: Test won't be stopped on fail 518 | * @see \Codeception\Lib\InnerBrowser::dontSeeCurrentUrlEquals() 519 | */ 520 | public function cantSeeCurrentUrlEquals($uri) { 521 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCurrentUrlEquals', func_get_args())); 522 | } 523 | /** 524 | * [!] Method is generated. Documentation taken from corresponding module. 525 | * 526 | * Checks that current url is not equal to value. 527 | * Unlike `dontSeeInCurrentUrl` performs a strict check. 528 | * 529 | * ``` php 530 | * dontSeeCurrentUrlEquals('/'); 533 | * ?> 534 | * ``` 535 | * 536 | * @param $uri 537 | * @see \Codeception\Lib\InnerBrowser::dontSeeCurrentUrlEquals() 538 | */ 539 | public function dontSeeCurrentUrlEquals($uri) { 540 | return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSeeCurrentUrlEquals', func_get_args())); 541 | } 542 | 543 | 544 | /** 545 | * [!] Method is generated. Documentation taken from corresponding module. 546 | * 547 | * Checks that current url is matches a RegEx value 548 | * 549 | * ``` php 550 | * seeCurrentUrlMatches('~$/users/(\d+)~'); 553 | * ?> 554 | * ``` 555 | * 556 | * @param $uri 557 | * Conditional Assertion: Test won't be stopped on fail 558 | * @see \Codeception\Lib\InnerBrowser::seeCurrentUrlMatches() 559 | */ 560 | public function canSeeCurrentUrlMatches($uri) { 561 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeCurrentUrlMatches', func_get_args())); 562 | } 563 | /** 564 | * [!] Method is generated. Documentation taken from corresponding module. 565 | * 566 | * Checks that current url is matches a RegEx value 567 | * 568 | * ``` php 569 | * seeCurrentUrlMatches('~$/users/(\d+)~'); 572 | * ?> 573 | * ``` 574 | * 575 | * @param $uri 576 | * @see \Codeception\Lib\InnerBrowser::seeCurrentUrlMatches() 577 | */ 578 | public function seeCurrentUrlMatches($uri) { 579 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeCurrentUrlMatches', func_get_args())); 580 | } 581 | 582 | 583 | /** 584 | * [!] Method is generated. Documentation taken from corresponding module. 585 | * 586 | * Checks that current url does not match a RegEx value 587 | * 588 | * ``` php 589 | * dontSeeCurrentUrlMatches('~$/users/(\d+)~'); 592 | * ?> 593 | * ``` 594 | * 595 | * @param $uri 596 | * Conditional Assertion: Test won't be stopped on fail 597 | * @see \Codeception\Lib\InnerBrowser::dontSeeCurrentUrlMatches() 598 | */ 599 | public function cantSeeCurrentUrlMatches($uri) { 600 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCurrentUrlMatches', func_get_args())); 601 | } 602 | /** 603 | * [!] Method is generated. Documentation taken from corresponding module. 604 | * 605 | * Checks that current url does not match a RegEx value 606 | * 607 | * ``` php 608 | * dontSeeCurrentUrlMatches('~$/users/(\d+)~'); 611 | * ?> 612 | * ``` 613 | * 614 | * @param $uri 615 | * @see \Codeception\Lib\InnerBrowser::dontSeeCurrentUrlMatches() 616 | */ 617 | public function dontSeeCurrentUrlMatches($uri) { 618 | return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSeeCurrentUrlMatches', func_get_args())); 619 | } 620 | 621 | 622 | /** 623 | * [!] Method is generated. Documentation taken from corresponding module. 624 | * 625 | * Takes a parameters from current URI by RegEx. 626 | * If no url provided returns full URI. 627 | * 628 | * ``` php 629 | * grabFromCurrentUrl('~$/user/(\d+)/~'); 631 | * $uri = $I->grabFromCurrentUrl(); 632 | * ?> 633 | * ``` 634 | * 635 | * @param null $uri 636 | * 637 | * @internal param $url 638 | * @return mixed 639 | * @see \Codeception\Lib\InnerBrowser::grabFromCurrentUrl() 640 | */ 641 | public function grabFromCurrentUrl($uri = null) { 642 | return $this->scenario->runStep(new \Codeception\Step\Action('grabFromCurrentUrl', func_get_args())); 643 | } 644 | 645 | 646 | /** 647 | * [!] Method is generated. Documentation taken from corresponding module. 648 | * 649 | * Assert if the specified checkbox is checked. 650 | * Use css selector or xpath to match. 651 | * 652 | * Example: 653 | * 654 | * ``` php 655 | * seeCheckboxIsChecked('#agree'); // I suppose user agreed to terms 657 | * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user agreed to terms, If there is only one checkbox in form. 658 | * $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); 659 | * ?> 660 | * ``` 661 | * 662 | * @param $checkbox 663 | * Conditional Assertion: Test won't be stopped on fail 664 | * @see \Codeception\Lib\InnerBrowser::seeCheckboxIsChecked() 665 | */ 666 | public function canSeeCheckboxIsChecked($checkbox) { 667 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeCheckboxIsChecked', func_get_args())); 668 | } 669 | /** 670 | * [!] Method is generated. Documentation taken from corresponding module. 671 | * 672 | * Assert if the specified checkbox is checked. 673 | * Use css selector or xpath to match. 674 | * 675 | * Example: 676 | * 677 | * ``` php 678 | * seeCheckboxIsChecked('#agree'); // I suppose user agreed to terms 680 | * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user agreed to terms, If there is only one checkbox in form. 681 | * $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); 682 | * ?> 683 | * ``` 684 | * 685 | * @param $checkbox 686 | * @see \Codeception\Lib\InnerBrowser::seeCheckboxIsChecked() 687 | */ 688 | public function seeCheckboxIsChecked($checkbox) { 689 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeCheckboxIsChecked', func_get_args())); 690 | } 691 | 692 | 693 | /** 694 | * [!] Method is generated. Documentation taken from corresponding module. 695 | * 696 | * Assert if the specified checkbox is unchecked. 697 | * Use css selector or xpath to match. 698 | * 699 | * Example: 700 | * 701 | * ``` php 702 | * dontSeeCheckboxIsChecked('#agree'); // I suppose user didn't agree to terms 704 | * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user didn't check the first checkbox in form. 705 | * ?> 706 | * ``` 707 | * 708 | * @param $checkbox 709 | * Conditional Assertion: Test won't be stopped on fail 710 | * @see \Codeception\Lib\InnerBrowser::dontSeeCheckboxIsChecked() 711 | */ 712 | public function cantSeeCheckboxIsChecked($checkbox) { 713 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCheckboxIsChecked', func_get_args())); 714 | } 715 | /** 716 | * [!] Method is generated. Documentation taken from corresponding module. 717 | * 718 | * Assert if the specified checkbox is unchecked. 719 | * Use css selector or xpath to match. 720 | * 721 | * Example: 722 | * 723 | * ``` php 724 | * dontSeeCheckboxIsChecked('#agree'); // I suppose user didn't agree to terms 726 | * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user didn't check the first checkbox in form. 727 | * ?> 728 | * ``` 729 | * 730 | * @param $checkbox 731 | * @see \Codeception\Lib\InnerBrowser::dontSeeCheckboxIsChecked() 732 | */ 733 | public function dontSeeCheckboxIsChecked($checkbox) { 734 | return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSeeCheckboxIsChecked', func_get_args())); 735 | } 736 | 737 | 738 | /** 739 | * [!] Method is generated. Documentation taken from corresponding module. 740 | * 741 | * Checks that an input field or textarea contains value. 742 | * Field is matched either by label or CSS or Xpath 743 | * 744 | * Example: 745 | * 746 | * ``` php 747 | * seeInField('Body','Type your comment here'); 749 | * $I->seeInField('form textarea[name=body]','Type your comment here'); 750 | * $I->seeInField('form input[type=hidden]','hidden_value'); 751 | * $I->seeInField('#searchform input','Search'); 752 | * $I->seeInField('//form/*[@name=search]','Search'); 753 | * $I->seeInField(['name' => 'search'], 'Search'); 754 | * ?> 755 | * ``` 756 | * 757 | * @param $field 758 | * @param $value 759 | * Conditional Assertion: Test won't be stopped on fail 760 | * @see \Codeception\Lib\InnerBrowser::seeInField() 761 | */ 762 | public function canSeeInField($field, $value) { 763 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeInField', func_get_args())); 764 | } 765 | /** 766 | * [!] Method is generated. Documentation taken from corresponding module. 767 | * 768 | * Checks that an input field or textarea contains value. 769 | * Field is matched either by label or CSS or Xpath 770 | * 771 | * Example: 772 | * 773 | * ``` php 774 | * seeInField('Body','Type your comment here'); 776 | * $I->seeInField('form textarea[name=body]','Type your comment here'); 777 | * $I->seeInField('form input[type=hidden]','hidden_value'); 778 | * $I->seeInField('#searchform input','Search'); 779 | * $I->seeInField('//form/*[@name=search]','Search'); 780 | * $I->seeInField(['name' => 'search'], 'Search'); 781 | * ?> 782 | * ``` 783 | * 784 | * @param $field 785 | * @param $value 786 | * @see \Codeception\Lib\InnerBrowser::seeInField() 787 | */ 788 | public function seeInField($field, $value) { 789 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeInField', func_get_args())); 790 | } 791 | 792 | 793 | /** 794 | * [!] Method is generated. Documentation taken from corresponding module. 795 | * 796 | * Checks that an input field or textarea doesn't contain value. 797 | * Field is matched either by label or CSS or Xpath 798 | * Example: 799 | * 800 | * ``` php 801 | * dontSeeInField('Body','Type your comment here'); 803 | * $I->dontSeeInField('form textarea[name=body]','Type your comment here'); 804 | * $I->dontSeeInField('form input[type=hidden]','hidden_value'); 805 | * $I->dontSeeInField('#searchform input','Search'); 806 | * $I->dontSeeInField('//form/*[@name=search]','Search'); 807 | * $I->seeInField(['name' => 'search'], 'Search'); 808 | * ?> 809 | * ``` 810 | * 811 | * @param $field 812 | * @param $value 813 | * Conditional Assertion: Test won't be stopped on fail 814 | * @see \Codeception\Lib\InnerBrowser::dontSeeInField() 815 | */ 816 | public function cantSeeInField($field, $value) { 817 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInField', func_get_args())); 818 | } 819 | /** 820 | * [!] Method is generated. Documentation taken from corresponding module. 821 | * 822 | * Checks that an input field or textarea doesn't contain value. 823 | * Field is matched either by label or CSS or Xpath 824 | * Example: 825 | * 826 | * ``` php 827 | * dontSeeInField('Body','Type your comment here'); 829 | * $I->dontSeeInField('form textarea[name=body]','Type your comment here'); 830 | * $I->dontSeeInField('form input[type=hidden]','hidden_value'); 831 | * $I->dontSeeInField('#searchform input','Search'); 832 | * $I->dontSeeInField('//form/*[@name=search]','Search'); 833 | * $I->seeInField(['name' => 'search'], 'Search'); 834 | * ?> 835 | * ``` 836 | * 837 | * @param $field 838 | * @param $value 839 | * @see \Codeception\Lib\InnerBrowser::dontSeeInField() 840 | */ 841 | public function dontSeeInField($field, $value) { 842 | return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSeeInField', func_get_args())); 843 | } 844 | 845 | 846 | /** 847 | * [!] Method is generated. Documentation taken from corresponding module. 848 | * 849 | * Submits a form located on page. 850 | * Specify the form by it's css or xpath selector. 851 | * Fill the form fields values as array. 852 | * 853 | * Skipped fields will be filled by their values from page. 854 | * You don't need to click the 'Submit' button afterwards. 855 | * This command itself triggers the request to form's action. 856 | * 857 | * You can optionally specify what button's value to include 858 | * in the request with the last parameter as an alternative to 859 | * explicitly setting its value in the second parameter, as 860 | * button values are not otherwise included in the request. 861 | * 862 | * Examples: 863 | * 864 | * ``` php 865 | * submitForm('#login', array('login' => 'davert', 'password' => '123456')); 867 | * // or 868 | * $I->submitForm('#login', array('login' => 'davert', 'password' => '123456'), 'submitButtonName'); 869 | * 870 | * ``` 871 | * 872 | * For a sample Sign Up form: 873 | * 874 | * ``` html 875 | *
876 | * Login:
877 | * Password:
878 | * Do you agree to out terms?
879 | * Select pricing plan 880 | * 881 | *
882 | * ``` 883 | * You could write the following to submit it: 884 | * 885 | * ``` php 886 | * submitForm('#userForm', array('user' => array('login' => 'Davert', 'password' => '123456', 'agree' => true)), 'submitButton'); 888 | * 889 | * ``` 890 | * Note that "2" will be the submitted value for the "plan" field, as it is the selected option. 891 | * 892 | * You can also emulate a JavaScript submission by not specifying any buttons in the third parameter to submitForm. 893 | * 894 | * ```php 895 | * submitForm('#userForm', array('user' => array('login' => 'Davert', 'password' => '123456', 'agree' => true))); 897 | * 898 | * ``` 899 | * 900 | * @param $selector 901 | * @param $params 902 | * @param $button 903 | * @see \Codeception\Lib\InnerBrowser::submitForm() 904 | */ 905 | public function submitForm($selector, $params, $button = null) { 906 | return $this->scenario->runStep(new \Codeception\Step\Action('submitForm', func_get_args())); 907 | } 908 | 909 | 910 | /** 911 | * [!] Method is generated. Documentation taken from corresponding module. 912 | * 913 | * Fills a text field or textarea with value. 914 | * 915 | * Example: 916 | * 917 | * ``` php 918 | * fillField("//input[@type='text']", "Hello World!"); 920 | * $I->fillField(['name' => 'email'], 'jon@mail.com'); 921 | * ?> 922 | * ``` 923 | * 924 | * @param $field 925 | * @param $value 926 | * @see \Codeception\Lib\InnerBrowser::fillField() 927 | */ 928 | public function fillField($field, $value) { 929 | return $this->scenario->runStep(new \Codeception\Step\Action('fillField', func_get_args())); 930 | } 931 | 932 | 933 | /** 934 | * [!] Method is generated. Documentation taken from corresponding module. 935 | * 936 | * Selects an option in select tag or in radio button group. 937 | * 938 | * Example: 939 | * 940 | * ``` php 941 | * selectOption('form select[name=account]', 'Premium'); 943 | * $I->selectOption('form input[name=payment]', 'Monthly'); 944 | * $I->selectOption('//form/select[@name=account]', 'Monthly'); 945 | * ?> 946 | * ``` 947 | * 948 | * Can select multiple options if second argument is array: 949 | * 950 | * ``` php 951 | * selectOption('Which OS do you use?', array('Windows','Linux')); 953 | * ?> 954 | * ``` 955 | * 956 | * @param $select 957 | * @param $option 958 | * @see \Codeception\Lib\InnerBrowser::selectOption() 959 | */ 960 | public function selectOption($select, $option) { 961 | return $this->scenario->runStep(new \Codeception\Step\Action('selectOption', func_get_args())); 962 | } 963 | 964 | 965 | /** 966 | * [!] Method is generated. Documentation taken from corresponding module. 967 | * 968 | * Ticks a checkbox. 969 | * For radio buttons use `selectOption` method. 970 | * 971 | * Example: 972 | * 973 | * ``` php 974 | * checkOption('#agree'); 976 | * ?> 977 | * ``` 978 | * 979 | * @param $option 980 | * @see \Codeception\Lib\InnerBrowser::checkOption() 981 | */ 982 | public function checkOption($option) { 983 | return $this->scenario->runStep(new \Codeception\Step\Action('checkOption', func_get_args())); 984 | } 985 | 986 | 987 | /** 988 | * [!] Method is generated. Documentation taken from corresponding module. 989 | * 990 | * Unticks a checkbox. 991 | * 992 | * Example: 993 | * 994 | * ``` php 995 | * uncheckOption('#notify'); 997 | * ?> 998 | * ``` 999 | * 1000 | * @param $option 1001 | * @see \Codeception\Lib\InnerBrowser::uncheckOption() 1002 | */ 1003 | public function uncheckOption($option) { 1004 | return $this->scenario->runStep(new \Codeception\Step\Action('uncheckOption', func_get_args())); 1005 | } 1006 | 1007 | 1008 | /** 1009 | * [!] Method is generated. Documentation taken from corresponding module. 1010 | * 1011 | * Attaches file from Codeception data directory to upload field. 1012 | * 1013 | * Example: 1014 | * 1015 | * ``` php 1016 | * attachFile('input[@type="file"]', 'prices.xls'); 1019 | * ?> 1020 | * ``` 1021 | * 1022 | * @param $field 1023 | * @param $filename 1024 | * @see \Codeception\Lib\InnerBrowser::attachFile() 1025 | */ 1026 | public function attachFile($field, $filename) { 1027 | return $this->scenario->runStep(new \Codeception\Step\Action('attachFile', func_get_args())); 1028 | } 1029 | 1030 | 1031 | /** 1032 | * [!] Method is generated. Documentation taken from corresponding module. 1033 | * 1034 | * If your page triggers an ajax request, you can perform it manually. 1035 | * This action sends a GET ajax request with specified params. 1036 | * 1037 | * See ->sendAjaxPostRequest for examples. 1038 | * 1039 | * @param $uri 1040 | * @param $params 1041 | * @see \Codeception\Lib\InnerBrowser::sendAjaxGetRequest() 1042 | */ 1043 | public function sendAjaxGetRequest($uri, $params = null) { 1044 | return $this->scenario->runStep(new \Codeception\Step\Action('sendAjaxGetRequest', func_get_args())); 1045 | } 1046 | 1047 | 1048 | /** 1049 | * [!] Method is generated. Documentation taken from corresponding module. 1050 | * 1051 | * If your page triggers an ajax request, you can perform it manually. 1052 | * This action sends a POST ajax request with specified params. 1053 | * Additional params can be passed as array. 1054 | * 1055 | * Example: 1056 | * 1057 | * Imagine that by clicking checkbox you trigger ajax request which updates user settings. 1058 | * We emulate that click by running this ajax request manually. 1059 | * 1060 | * ``` php 1061 | * sendAjaxPostRequest('/updateSettings', array('notifications' => true)); // POST 1063 | * $I->sendAjaxGetRequest('/updateSettings', array('notifications' => true)); // GET 1064 | * 1065 | * ``` 1066 | * 1067 | * @param $uri 1068 | * @param $params 1069 | * @see \Codeception\Lib\InnerBrowser::sendAjaxPostRequest() 1070 | */ 1071 | public function sendAjaxPostRequest($uri, $params = null) { 1072 | return $this->scenario->runStep(new \Codeception\Step\Action('sendAjaxPostRequest', func_get_args())); 1073 | } 1074 | 1075 | 1076 | /** 1077 | * [!] Method is generated. Documentation taken from corresponding module. 1078 | * 1079 | * If your page triggers an ajax request, you can perform it manually. 1080 | * This action sends an ajax request with specified method and params. 1081 | * 1082 | * Example: 1083 | * 1084 | * You need to perform an ajax request specifying the HTTP method. 1085 | * 1086 | * ``` php 1087 | * sendAjaxRequest('PUT', '/posts/7', array('title' => 'new title')); 1089 | * 1090 | * ``` 1091 | * 1092 | * @param $method 1093 | * @param $uri 1094 | * @param $params 1095 | * @see \Codeception\Lib\InnerBrowser::sendAjaxRequest() 1096 | */ 1097 | public function sendAjaxRequest($method, $uri, $params = null) { 1098 | return $this->scenario->runStep(new \Codeception\Step\Action('sendAjaxRequest', func_get_args())); 1099 | } 1100 | 1101 | 1102 | /** 1103 | * [!] Method is generated. Documentation taken from corresponding module. 1104 | * 1105 | * Finds and returns text contents of element. 1106 | * Element is searched by CSS selector, XPath or matcher by regex. 1107 | * 1108 | * Example: 1109 | * 1110 | * ``` php 1111 | * grabTextFrom('h1'); 1113 | * $heading = $I->grabTextFrom('descendant-or-self::h1'); 1114 | * $value = $I->grabTextFrom('~ 1116 | * ``` 1117 | * 1118 | * @param $cssOrXPathOrRegex 1119 | * 1120 | * @return mixed 1121 | * @see \Codeception\Lib\InnerBrowser::grabTextFrom() 1122 | */ 1123 | public function grabTextFrom($cssOrXPathOrRegex) { 1124 | return $this->scenario->runStep(new \Codeception\Step\Action('grabTextFrom', func_get_args())); 1125 | } 1126 | 1127 | 1128 | /** 1129 | * [!] Method is generated. Documentation taken from corresponding module. 1130 | * 1131 | * Grabs attribute value from an element. 1132 | * Fails if element is not found. 1133 | * 1134 | * ``` php 1135 | * grabAttributeFrom('#tooltip', 'title'); 1137 | * ?> 1138 | * ``` 1139 | * 1140 | * 1141 | * @param $cssOrXpath 1142 | * @param $attribute 1143 | * @internal param $element 1144 | * @return mixed 1145 | * @see \Codeception\Lib\InnerBrowser::grabAttributeFrom() 1146 | */ 1147 | public function grabAttributeFrom($cssOrXpath, $attribute) { 1148 | return $this->scenario->runStep(new \Codeception\Step\Action('grabAttributeFrom', func_get_args())); 1149 | } 1150 | 1151 | 1152 | /** 1153 | * [!] Method is generated. Documentation taken from corresponding module. 1154 | * 1155 | * @param $field 1156 | * 1157 | * @return array|mixed|null|string 1158 | * @see \Codeception\Lib\InnerBrowser::grabValueFrom() 1159 | */ 1160 | public function grabValueFrom($field) { 1161 | return $this->scenario->runStep(new \Codeception\Step\Action('grabValueFrom', func_get_args())); 1162 | } 1163 | 1164 | 1165 | /** 1166 | * [!] Method is generated. Documentation taken from corresponding module. 1167 | * 1168 | * Sets a cookie. 1169 | * 1170 | * @param $cookie 1171 | * @param $value 1172 | * 1173 | * @return mixed 1174 | * @see \Codeception\Lib\InnerBrowser::setCookie() 1175 | */ 1176 | public function setCookie($name, $val) { 1177 | return $this->scenario->runStep(new \Codeception\Step\Action('setCookie', func_get_args())); 1178 | } 1179 | 1180 | 1181 | /** 1182 | * [!] Method is generated. Documentation taken from corresponding module. 1183 | * 1184 | * Grabs a cookie value. 1185 | * 1186 | * @param $cookie 1187 | * 1188 | * @return mixed 1189 | * @see \Codeception\Lib\InnerBrowser::grabCookie() 1190 | */ 1191 | public function grabCookie($name) { 1192 | return $this->scenario->runStep(new \Codeception\Step\Action('grabCookie', func_get_args())); 1193 | } 1194 | 1195 | 1196 | /** 1197 | * [!] Method is generated. Documentation taken from corresponding module. 1198 | * 1199 | * Checks that cookie is set. 1200 | * 1201 | * @param $cookie 1202 | * 1203 | * @return mixed 1204 | * Conditional Assertion: Test won't be stopped on fail 1205 | * @see \Codeception\Lib\InnerBrowser::seeCookie() 1206 | */ 1207 | public function canSeeCookie($name) { 1208 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeCookie', func_get_args())); 1209 | } 1210 | /** 1211 | * [!] Method is generated. Documentation taken from corresponding module. 1212 | * 1213 | * Checks that cookie is set. 1214 | * 1215 | * @param $cookie 1216 | * 1217 | * @return mixed 1218 | * @see \Codeception\Lib\InnerBrowser::seeCookie() 1219 | */ 1220 | public function seeCookie($name) { 1221 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeCookie', func_get_args())); 1222 | } 1223 | 1224 | 1225 | /** 1226 | * [!] Method is generated. Documentation taken from corresponding module. 1227 | * 1228 | * Checks that cookie doesn't exist 1229 | * 1230 | * @param $cookie 1231 | * 1232 | * @return mixed 1233 | * Conditional Assertion: Test won't be stopped on fail 1234 | * @see \Codeception\Lib\InnerBrowser::dontSeeCookie() 1235 | */ 1236 | public function cantSeeCookie($name) { 1237 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCookie', func_get_args())); 1238 | } 1239 | /** 1240 | * [!] Method is generated. Documentation taken from corresponding module. 1241 | * 1242 | * Checks that cookie doesn't exist 1243 | * 1244 | * @param $cookie 1245 | * 1246 | * @return mixed 1247 | * @see \Codeception\Lib\InnerBrowser::dontSeeCookie() 1248 | */ 1249 | public function dontSeeCookie($name) { 1250 | return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSeeCookie', func_get_args())); 1251 | } 1252 | 1253 | 1254 | /** 1255 | * [!] Method is generated. Documentation taken from corresponding module. 1256 | * 1257 | * Unsets cookie 1258 | * 1259 | * @param $cookie 1260 | * 1261 | * @return mixed 1262 | * @see \Codeception\Lib\InnerBrowser::resetCookie() 1263 | */ 1264 | public function resetCookie($name) { 1265 | return $this->scenario->runStep(new \Codeception\Step\Action('resetCookie', func_get_args())); 1266 | } 1267 | 1268 | 1269 | /** 1270 | * [!] Method is generated. Documentation taken from corresponding module. 1271 | * 1272 | * Checks if element exists on a page, matching it by CSS or XPath. 1273 | * You can also specify expected attributes of this element. 1274 | * 1275 | * ``` php 1276 | * seeElement('.error'); 1278 | * $I->seeElement('//form/input[1]'); 1279 | * $I->seeElement('input', ['name' => 'login']); 1280 | * $I->seeElement('input', ['value' => '123456']); 1281 | * 1282 | * // strict locator in first arg, attributes in second 1283 | * $I->seeElement(['css' => 'form input'], ['name' => 'login']); 1284 | * ?> 1285 | * ``` 1286 | * 1287 | * @param $selector 1288 | * @param array $attributes 1289 | * @return 1290 | * Conditional Assertion: Test won't be stopped on fail 1291 | * @see \Codeception\Lib\InnerBrowser::seeElement() 1292 | */ 1293 | public function canSeeElement($selector, $attributes = null) { 1294 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeElement', func_get_args())); 1295 | } 1296 | /** 1297 | * [!] Method is generated. Documentation taken from corresponding module. 1298 | * 1299 | * Checks if element exists on a page, matching it by CSS or XPath. 1300 | * You can also specify expected attributes of this element. 1301 | * 1302 | * ``` php 1303 | * seeElement('.error'); 1305 | * $I->seeElement('//form/input[1]'); 1306 | * $I->seeElement('input', ['name' => 'login']); 1307 | * $I->seeElement('input', ['value' => '123456']); 1308 | * 1309 | * // strict locator in first arg, attributes in second 1310 | * $I->seeElement(['css' => 'form input'], ['name' => 'login']); 1311 | * ?> 1312 | * ``` 1313 | * 1314 | * @param $selector 1315 | * @param array $attributes 1316 | * @return 1317 | * @see \Codeception\Lib\InnerBrowser::seeElement() 1318 | */ 1319 | public function seeElement($selector, $attributes = null) { 1320 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeElement', func_get_args())); 1321 | } 1322 | 1323 | 1324 | /** 1325 | * [!] Method is generated. Documentation taken from corresponding module. 1326 | * 1327 | * Checks if element does not exist (or is visible) on a page, matching it by CSS or XPath 1328 | * You can also specify expected attributes of this element. 1329 | * 1330 | * Example: 1331 | * 1332 | * ``` php 1333 | * dontSeeElement('.error'); 1335 | * $I->dontSeeElement('//form/input[1]'); 1336 | * $I->dontSeeElement('input', ['name' => 'login']); 1337 | * $I->dontSeeElement('input', ['value' => '123456']); 1338 | * ?> 1339 | * ``` 1340 | * 1341 | * @param $selector 1342 | * Conditional Assertion: Test won't be stopped on fail 1343 | * @see \Codeception\Lib\InnerBrowser::dontSeeElement() 1344 | */ 1345 | public function cantSeeElement($selector, $attributes = null) { 1346 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeElement', func_get_args())); 1347 | } 1348 | /** 1349 | * [!] Method is generated. Documentation taken from corresponding module. 1350 | * 1351 | * Checks if element does not exist (or is visible) on a page, matching it by CSS or XPath 1352 | * You can also specify expected attributes of this element. 1353 | * 1354 | * Example: 1355 | * 1356 | * ``` php 1357 | * dontSeeElement('.error'); 1359 | * $I->dontSeeElement('//form/input[1]'); 1360 | * $I->dontSeeElement('input', ['name' => 'login']); 1361 | * $I->dontSeeElement('input', ['value' => '123456']); 1362 | * ?> 1363 | * ``` 1364 | * 1365 | * @param $selector 1366 | * @see \Codeception\Lib\InnerBrowser::dontSeeElement() 1367 | */ 1368 | public function dontSeeElement($selector, $attributes = null) { 1369 | return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSeeElement', func_get_args())); 1370 | } 1371 | 1372 | 1373 | /** 1374 | * [!] Method is generated. Documentation taken from corresponding module. 1375 | * 1376 | * Tests number of $elements on page 1377 | * 1378 | * ``` php 1379 | * seeNumberOfElements('tr', 10); 1381 | * $I->seeNumberOfElements('tr', [0,10]); //between 0 and 10 elements 1382 | * ?> 1383 | * ``` 1384 | * @param $selector 1385 | * @param mixed $expected: 1386 | * - string: strict number 1387 | * - array: range of numbers [0,10] 1388 | * Conditional Assertion: Test won't be stopped on fail 1389 | * @see \Codeception\Lib\InnerBrowser::seeNumberOfElements() 1390 | */ 1391 | public function canSeeNumberOfElements($selector, $expected) { 1392 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeNumberOfElements', func_get_args())); 1393 | } 1394 | /** 1395 | * [!] Method is generated. Documentation taken from corresponding module. 1396 | * 1397 | * Tests number of $elements on page 1398 | * 1399 | * ``` php 1400 | * seeNumberOfElements('tr', 10); 1402 | * $I->seeNumberOfElements('tr', [0,10]); //between 0 and 10 elements 1403 | * ?> 1404 | * ``` 1405 | * @param $selector 1406 | * @param mixed $expected: 1407 | * - string: strict number 1408 | * - array: range of numbers [0,10] 1409 | * @see \Codeception\Lib\InnerBrowser::seeNumberOfElements() 1410 | */ 1411 | public function seeNumberOfElements($selector, $expected) { 1412 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeNumberOfElements', func_get_args())); 1413 | } 1414 | 1415 | 1416 | /** 1417 | * [!] Method is generated. Documentation taken from corresponding module. 1418 | * 1419 | * Checks if option is selected in select field. 1420 | * 1421 | * ``` php 1422 | * seeOptionIsSelected('#form input[name=payment]', 'Visa'); 1424 | * ?> 1425 | * ``` 1426 | * 1427 | * @param $selector 1428 | * @param $optionText 1429 | * 1430 | * @return mixed 1431 | * Conditional Assertion: Test won't be stopped on fail 1432 | * @see \Codeception\Lib\InnerBrowser::seeOptionIsSelected() 1433 | */ 1434 | public function canSeeOptionIsSelected($select, $optionText) { 1435 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeOptionIsSelected', func_get_args())); 1436 | } 1437 | /** 1438 | * [!] Method is generated. Documentation taken from corresponding module. 1439 | * 1440 | * Checks if option is selected in select field. 1441 | * 1442 | * ``` php 1443 | * seeOptionIsSelected('#form input[name=payment]', 'Visa'); 1445 | * ?> 1446 | * ``` 1447 | * 1448 | * @param $selector 1449 | * @param $optionText 1450 | * 1451 | * @return mixed 1452 | * @see \Codeception\Lib\InnerBrowser::seeOptionIsSelected() 1453 | */ 1454 | public function seeOptionIsSelected($select, $optionText) { 1455 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeOptionIsSelected', func_get_args())); 1456 | } 1457 | 1458 | 1459 | /** 1460 | * [!] Method is generated. Documentation taken from corresponding module. 1461 | * 1462 | * Checks if option is not selected in select field. 1463 | * 1464 | * ``` php 1465 | * dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); 1467 | * ?> 1468 | * ``` 1469 | * 1470 | * @param $selector 1471 | * @param $optionText 1472 | * 1473 | * @return mixed 1474 | * Conditional Assertion: Test won't be stopped on fail 1475 | * @see \Codeception\Lib\InnerBrowser::dontSeeOptionIsSelected() 1476 | */ 1477 | public function cantSeeOptionIsSelected($select, $optionText) { 1478 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeOptionIsSelected', func_get_args())); 1479 | } 1480 | /** 1481 | * [!] Method is generated. Documentation taken from corresponding module. 1482 | * 1483 | * Checks if option is not selected in select field. 1484 | * 1485 | * ``` php 1486 | * dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); 1488 | * ?> 1489 | * ``` 1490 | * 1491 | * @param $selector 1492 | * @param $optionText 1493 | * 1494 | * @return mixed 1495 | * @see \Codeception\Lib\InnerBrowser::dontSeeOptionIsSelected() 1496 | */ 1497 | public function dontSeeOptionIsSelected($select, $optionText) { 1498 | return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSeeOptionIsSelected', func_get_args())); 1499 | } 1500 | 1501 | 1502 | /** 1503 | * [!] Method is generated. Documentation taken from corresponding module. 1504 | * 1505 | * Asserts that current page has 404 response status code. 1506 | * Conditional Assertion: Test won't be stopped on fail 1507 | * @see \Codeception\Lib\InnerBrowser::seePageNotFound() 1508 | */ 1509 | public function canSeePageNotFound() { 1510 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seePageNotFound', func_get_args())); 1511 | } 1512 | /** 1513 | * [!] Method is generated. Documentation taken from corresponding module. 1514 | * 1515 | * Asserts that current page has 404 response status code. 1516 | * @see \Codeception\Lib\InnerBrowser::seePageNotFound() 1517 | */ 1518 | public function seePageNotFound() { 1519 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seePageNotFound', func_get_args())); 1520 | } 1521 | 1522 | 1523 | /** 1524 | * [!] Method is generated. Documentation taken from corresponding module. 1525 | * 1526 | * Checks that response code is equal to value provided. 1527 | * 1528 | * @param $code 1529 | * 1530 | * @return mixed 1531 | * Conditional Assertion: Test won't be stopped on fail 1532 | * @see \Codeception\Lib\InnerBrowser::seeResponseCodeIs() 1533 | */ 1534 | public function canSeeResponseCodeIs($code) { 1535 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeResponseCodeIs', func_get_args())); 1536 | } 1537 | /** 1538 | * [!] Method is generated. Documentation taken from corresponding module. 1539 | * 1540 | * Checks that response code is equal to value provided. 1541 | * 1542 | * @param $code 1543 | * 1544 | * @return mixed 1545 | * @see \Codeception\Lib\InnerBrowser::seeResponseCodeIs() 1546 | */ 1547 | public function seeResponseCodeIs($code) { 1548 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeResponseCodeIs', func_get_args())); 1549 | } 1550 | 1551 | 1552 | /** 1553 | * [!] Method is generated. Documentation taken from corresponding module. 1554 | * 1555 | * Checks that page title contains text. 1556 | * 1557 | * ``` php 1558 | * seeInTitle('Blog - Post #1'); 1560 | * ?> 1561 | * ``` 1562 | * 1563 | * @param $title 1564 | * 1565 | * @return mixed 1566 | * Conditional Assertion: Test won't be stopped on fail 1567 | * @see \Codeception\Lib\InnerBrowser::seeInTitle() 1568 | */ 1569 | public function canSeeInTitle($title) { 1570 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeInTitle', func_get_args())); 1571 | } 1572 | /** 1573 | * [!] Method is generated. Documentation taken from corresponding module. 1574 | * 1575 | * Checks that page title contains text. 1576 | * 1577 | * ``` php 1578 | * seeInTitle('Blog - Post #1'); 1580 | * ?> 1581 | * ``` 1582 | * 1583 | * @param $title 1584 | * 1585 | * @return mixed 1586 | * @see \Codeception\Lib\InnerBrowser::seeInTitle() 1587 | */ 1588 | public function seeInTitle($title) { 1589 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeInTitle', func_get_args())); 1590 | } 1591 | 1592 | 1593 | /** 1594 | * [!] Method is generated. Documentation taken from corresponding module. 1595 | * 1596 | * Checks that page title does not contain text. 1597 | * 1598 | * @param $title 1599 | * 1600 | * @return mixed 1601 | * Conditional Assertion: Test won't be stopped on fail 1602 | * @see \Codeception\Lib\InnerBrowser::dontSeeInTitle() 1603 | */ 1604 | public function cantSeeInTitle($title) { 1605 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInTitle', func_get_args())); 1606 | } 1607 | /** 1608 | * [!] Method is generated. Documentation taken from corresponding module. 1609 | * 1610 | * Checks that page title does not contain text. 1611 | * 1612 | * @param $title 1613 | * 1614 | * @return mixed 1615 | * @see \Codeception\Lib\InnerBrowser::dontSeeInTitle() 1616 | */ 1617 | public function dontSeeInTitle($title) { 1618 | return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSeeInTitle', func_get_args())); 1619 | } 1620 | } 1621 | -------------------------------------------------------------------------------- /tests/acceptance/_bootstrap.php: -------------------------------------------------------------------------------- 1 | scenario->runStep(new \Codeception\Step\Condition('amInPath', func_get_args())); 38 | } 39 | 40 | 41 | /** 42 | * [!] Method is generated. Documentation taken from corresponding module. 43 | * 44 | * Opens a file and stores it's content. 45 | * 46 | * Usage: 47 | * 48 | * ``` php 49 | * openFile('composer.json'); 51 | * $I->seeInThisFile('codeception/codeception'); 52 | * ?> 53 | * ``` 54 | * 55 | * @param $filename 56 | * @see \Codeception\Module\Filesystem::openFile() 57 | */ 58 | public function openFile($filename) { 59 | return $this->scenario->runStep(new \Codeception\Step\Action('openFile', func_get_args())); 60 | } 61 | 62 | 63 | /** 64 | * [!] Method is generated. Documentation taken from corresponding module. 65 | * 66 | * Deletes a file 67 | * 68 | * ``` php 69 | * deleteFile('composer.lock'); 71 | * ?> 72 | * ``` 73 | * 74 | * @param $filename 75 | * @see \Codeception\Module\Filesystem::deleteFile() 76 | */ 77 | public function deleteFile($filename) { 78 | return $this->scenario->runStep(new \Codeception\Step\Action('deleteFile', func_get_args())); 79 | } 80 | 81 | 82 | /** 83 | * [!] Method is generated. Documentation taken from corresponding module. 84 | * 85 | * Deletes directory with all subdirectories 86 | * 87 | * ``` php 88 | * deleteDir('vendor'); 90 | * ?> 91 | * ``` 92 | * 93 | * @param $dirname 94 | * @see \Codeception\Module\Filesystem::deleteDir() 95 | */ 96 | public function deleteDir($dirname) { 97 | return $this->scenario->runStep(new \Codeception\Step\Action('deleteDir', func_get_args())); 98 | } 99 | 100 | 101 | /** 102 | * [!] Method is generated. Documentation taken from corresponding module. 103 | * 104 | * Copies directory with all contents 105 | * 106 | * ``` php 107 | * copyDir('vendor','old_vendor'); 109 | * ?> 110 | * ``` 111 | * 112 | * @param $src 113 | * @param $dst 114 | * @see \Codeception\Module\Filesystem::copyDir() 115 | */ 116 | public function copyDir($src, $dst) { 117 | return $this->scenario->runStep(new \Codeception\Step\Action('copyDir', func_get_args())); 118 | } 119 | 120 | 121 | /** 122 | * [!] Method is generated. Documentation taken from corresponding module. 123 | * 124 | * Checks If opened file has `text` in it. 125 | * 126 | * Usage: 127 | * 128 | * ``` php 129 | * openFile('composer.json'); 131 | * $I->seeInThisFile('codeception/codeception'); 132 | * ?> 133 | * ``` 134 | * 135 | * @param $text 136 | * Conditional Assertion: Test won't be stopped on fail 137 | * @see \Codeception\Module\Filesystem::seeInThisFile() 138 | */ 139 | public function canSeeInThisFile($text) { 140 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeInThisFile', func_get_args())); 141 | } 142 | /** 143 | * [!] Method is generated. Documentation taken from corresponding module. 144 | * 145 | * Checks If opened file has `text` in it. 146 | * 147 | * Usage: 148 | * 149 | * ``` php 150 | * openFile('composer.json'); 152 | * $I->seeInThisFile('codeception/codeception'); 153 | * ?> 154 | * ``` 155 | * 156 | * @param $text 157 | * @see \Codeception\Module\Filesystem::seeInThisFile() 158 | */ 159 | public function seeInThisFile($text) { 160 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeInThisFile', func_get_args())); 161 | } 162 | 163 | 164 | /** 165 | * [!] Method is generated. Documentation taken from corresponding module. 166 | * 167 | * Checks the strict matching of file contents. 168 | * Unlike `seeInThisFile` will fail if file has something more than expected lines. 169 | * Better to use with HEREDOC strings. 170 | * Matching is done after removing "\r" chars from file content. 171 | * 172 | * ``` php 173 | * openFile('process.pid'); 175 | * $I->seeFileContentsEqual('3192'); 176 | * ?> 177 | * ``` 178 | * 179 | * @param $text 180 | * Conditional Assertion: Test won't be stopped on fail 181 | * @see \Codeception\Module\Filesystem::seeFileContentsEqual() 182 | */ 183 | public function canSeeFileContentsEqual($text) { 184 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeFileContentsEqual', func_get_args())); 185 | } 186 | /** 187 | * [!] Method is generated. Documentation taken from corresponding module. 188 | * 189 | * Checks the strict matching of file contents. 190 | * Unlike `seeInThisFile` will fail if file has something more than expected lines. 191 | * Better to use with HEREDOC strings. 192 | * Matching is done after removing "\r" chars from file content. 193 | * 194 | * ``` php 195 | * openFile('process.pid'); 197 | * $I->seeFileContentsEqual('3192'); 198 | * ?> 199 | * ``` 200 | * 201 | * @param $text 202 | * @see \Codeception\Module\Filesystem::seeFileContentsEqual() 203 | */ 204 | public function seeFileContentsEqual($text) { 205 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeFileContentsEqual', func_get_args())); 206 | } 207 | 208 | 209 | /** 210 | * [!] Method is generated. Documentation taken from corresponding module. 211 | * 212 | * Checks If opened file doesn't contain `text` in it 213 | * 214 | * ``` php 215 | * openFile('composer.json'); 217 | * $I->dontSeeInThisFile('codeception/codeception'); 218 | * ?> 219 | * ``` 220 | * 221 | * @param $text 222 | * Conditional Assertion: Test won't be stopped on fail 223 | * @see \Codeception\Module\Filesystem::dontSeeInThisFile() 224 | */ 225 | public function cantSeeInThisFile($text) { 226 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInThisFile', func_get_args())); 227 | } 228 | /** 229 | * [!] Method is generated. Documentation taken from corresponding module. 230 | * 231 | * Checks If opened file doesn't contain `text` in it 232 | * 233 | * ``` php 234 | * openFile('composer.json'); 236 | * $I->dontSeeInThisFile('codeception/codeception'); 237 | * ?> 238 | * ``` 239 | * 240 | * @param $text 241 | * @see \Codeception\Module\Filesystem::dontSeeInThisFile() 242 | */ 243 | public function dontSeeInThisFile($text) { 244 | return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSeeInThisFile', func_get_args())); 245 | } 246 | 247 | 248 | /** 249 | * [!] Method is generated. Documentation taken from corresponding module. 250 | * 251 | * Deletes a file 252 | * @see \Codeception\Module\Filesystem::deleteThisFile() 253 | */ 254 | public function deleteThisFile() { 255 | return $this->scenario->runStep(new \Codeception\Step\Action('deleteThisFile', func_get_args())); 256 | } 257 | 258 | 259 | /** 260 | * [!] Method is generated. Documentation taken from corresponding module. 261 | * 262 | * Checks if file exists in path. 263 | * Opens a file when it's exists 264 | * 265 | * ``` php 266 | * seeFileFound('UserModel.php','app/models'); 268 | * ?> 269 | * ``` 270 | * 271 | * @param $filename 272 | * @param string $path 273 | * Conditional Assertion: Test won't be stopped on fail 274 | * @see \Codeception\Module\Filesystem::seeFileFound() 275 | */ 276 | public function canSeeFileFound($filename, $path = null) { 277 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('seeFileFound', func_get_args())); 278 | } 279 | /** 280 | * [!] Method is generated. Documentation taken from corresponding module. 281 | * 282 | * Checks if file exists in path. 283 | * Opens a file when it's exists 284 | * 285 | * ``` php 286 | * seeFileFound('UserModel.php','app/models'); 288 | * ?> 289 | * ``` 290 | * 291 | * @param $filename 292 | * @param string $path 293 | * @see \Codeception\Module\Filesystem::seeFileFound() 294 | */ 295 | public function seeFileFound($filename, $path = null) { 296 | return $this->scenario->runStep(new \Codeception\Step\Assertion('seeFileFound', func_get_args())); 297 | } 298 | 299 | 300 | /** 301 | * [!] Method is generated. Documentation taken from corresponding module. 302 | * 303 | * Checks if file does not exists in path 304 | * 305 | * @param $filename 306 | * @param string $path 307 | * Conditional Assertion: Test won't be stopped on fail 308 | * @see \Codeception\Module\Filesystem::dontSeeFileFound() 309 | */ 310 | public function cantSeeFileFound($filename, $path = null) { 311 | return $this->scenario->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeFileFound', func_get_args())); 312 | } 313 | /** 314 | * [!] Method is generated. Documentation taken from corresponding module. 315 | * 316 | * Checks if file does not exists in path 317 | * 318 | * @param $filename 319 | * @param string $path 320 | * @see \Codeception\Module\Filesystem::dontSeeFileFound() 321 | */ 322 | public function dontSeeFileFound($filename, $path = null) { 323 | return $this->scenario->runStep(new \Codeception\Step\Assertion('dontSeeFileFound', func_get_args())); 324 | } 325 | 326 | 327 | /** 328 | * [!] Method is generated. Documentation taken from corresponding module. 329 | * 330 | * Erases directory contents 331 | * 332 | * ``` php 333 | * cleanDir('logs'); 335 | * ?> 336 | * ``` 337 | * 338 | * @param $dirname 339 | * @see \Codeception\Module\Filesystem::cleanDir() 340 | */ 341 | public function cleanDir($dirname) { 342 | return $this->scenario->runStep(new \Codeception\Step\Action('cleanDir', func_get_args())); 343 | } 344 | 345 | 346 | /** 347 | * [!] Method is generated. Documentation taken from corresponding module. 348 | * 349 | * Saves contents to file 350 | * 351 | * @param $filename 352 | * @param $contents 353 | * @see \Codeception\Module\Filesystem::writeToFile() 354 | */ 355 | public function writeToFile($filename, $contents) { 356 | return $this->scenario->runStep(new \Codeception\Step\Action('writeToFile', func_get_args())); 357 | } 358 | } 359 | -------------------------------------------------------------------------------- /tests/functional/_bootstrap.php: -------------------------------------------------------------------------------- 1 | key = m::mock("ApiKeysModel"); 15 | 16 | $this->key->shouldReceive("getApiLogs")->andReturn( 17 | [ 18 | 1, 19 | 2, 20 | 3, 21 | 4, 22 | 5, 23 | 6, 24 | 7, 25 | 8, 26 | 9, 27 | 20 28 | ] 29 | ); 30 | } 31 | 32 | protected function tearDown() 33 | { 34 | 35 | } 36 | 37 | // tests 38 | public function testKeyLimit() 39 | { 40 | try { 41 | $this->assertTrue(Key::get($this->key, "-1 day", 11)->checkLimit()); 42 | } catch (\Phalcon\Exception $e) { 43 | $this->assertNotEquals("Limit reached", $e->getMessage()); 44 | } 45 | } 46 | 47 | public function testKeyLimitReached() 48 | { 49 | try { 50 | $this->assertFalse(Key::get($this->key, "-1 day", 9)->checkLimit()); 51 | } catch (\Phalcon\Exception $e) { 52 | $this->assertEquals("Limit reached", $e->getMessage()); 53 | } 54 | } 55 | 56 | public function testMethodLimit() 57 | { 58 | try { 59 | $this->assertTrue(Method::get($this->key, "/v1/key", "POST", "-1 day", 11)->checkLimit()); 60 | } catch (\Phalcon\Exception $e) { 61 | $this->assertNotEquals("Limit reached", $e->getMessage()); 62 | } 63 | } 64 | 65 | public function testMethodLimitReached() 66 | { 67 | try { 68 | $this->assertFalse(Method::get($this->key, "/v1/key", "POST", "-1 day", 9)->checkLimit()); 69 | } catch (\Phalcon\Exception $e) { 70 | $this->assertEquals("Limit reached", $e->getMessage()); 71 | } 72 | } 73 | 74 | } -------------------------------------------------------------------------------- /tests/unit/AuthTest.php: -------------------------------------------------------------------------------- 1 | setDI(\Phalcon\DI::getDefault()); 23 | $this->assertTrue($auth->auth()); 24 | } catch (\Jowy\Phrest\Core\Exception\InvalidAuthException $e) { 25 | $this->fail("Invalid Auth"); 26 | } catch (\Phalcon\Exception $e) { 27 | $this->fail("Class not found"); 28 | } 29 | 30 | } 31 | 32 | public function testAuthFail() 33 | { 34 | try { 35 | $auth = \Jowy\Phrest\Core\Auth::create("basic"); 36 | $auth->setDI(\Phalcon\DI::getDefault()); 37 | $_SERVER["PHP_AUTH_PW"] = "Wrong PW"; 38 | $this->assertTrue($auth->auth()); 39 | } catch (\Jowy\Phrest\Core\Exception\InvalidAuthException $e) { 40 | $this->assertEquals(401, $e->getCode()); 41 | } catch (\Phalcon\Exception $e) { 42 | $this->fail("Class not found"); 43 | } 44 | } 45 | 46 | public function testAuthClassNotFound() 47 | { 48 | try { 49 | $auth = \Jowy\Phrest\Core\Auth::create("notExist"); 50 | $auth->setDI(\Phalcon\DI::getDefault()); 51 | $this->assertTrue($auth->auth()); 52 | } catch (\Jowy\Phrest\Core\Exception\InvalidAuthException $e) { 53 | $this->fail("Class not found"); 54 | } catch (\Phalcon\Exception $e) { 55 | $this->assertEquals(500, $e->getCode()); 56 | } 57 | } 58 | 59 | } -------------------------------------------------------------------------------- /tests/unit/UnitTester.php: -------------------------------------------------------------------------------- 1 | scenario->runStep(new \Codeception\Step\Action('assertEquals', func_get_args())); 42 | } 43 | 44 | 45 | /** 46 | * [!] Method is generated. Documentation taken from corresponding module. 47 | * 48 | * Checks that two variables are not equal 49 | * 50 | * @param $expected 51 | * @param $actual 52 | * @param string $message 53 | * @see \Codeception\Module\Asserts::assertNotEquals() 54 | */ 55 | public function assertNotEquals($expected, $actual, $message = null) { 56 | return $this->scenario->runStep(new \Codeception\Step\Action('assertNotEquals', func_get_args())); 57 | } 58 | 59 | 60 | /** 61 | * [!] Method is generated. Documentation taken from corresponding module. 62 | * 63 | * Checks that expected is greater than actual 64 | * 65 | * @param $expected 66 | * @param $actual 67 | * @param string $message 68 | * @see \Codeception\Module\Asserts::assertGreaterThan() 69 | */ 70 | public function assertGreaterThan($expected, $actual, $message = null) { 71 | return $this->scenario->runStep(new \Codeception\Step\Action('assertGreaterThan', func_get_args())); 72 | } 73 | 74 | 75 | /** 76 | * [!] Method is generated. Documentation taken from corresponding module. 77 | * 78 | * @deprecated 79 | * @see \Codeception\Module\Asserts::assertGreaterThen() 80 | */ 81 | public function assertGreaterThen($expected, $actual, $message = null) { 82 | return $this->scenario->runStep(new \Codeception\Step\Action('assertGreaterThen', func_get_args())); 83 | } 84 | 85 | 86 | /** 87 | * [!] Method is generated. Documentation taken from corresponding module. 88 | * 89 | * Checks that expected is greater or equal than actual 90 | * 91 | * @param $expected 92 | * @param $actual 93 | * @param string $message 94 | * @see \Codeception\Module\Asserts::assertGreaterThanOrEqual() 95 | */ 96 | public function assertGreaterThanOrEqual($expected, $actual, $message = null) { 97 | return $this->scenario->runStep(new \Codeception\Step\Action('assertGreaterThanOrEqual', func_get_args())); 98 | } 99 | 100 | 101 | /** 102 | * [!] Method is generated. Documentation taken from corresponding module. 103 | * 104 | * @deprecated 105 | * @see \Codeception\Module\Asserts::assertGreaterThenOrEqual() 106 | */ 107 | public function assertGreaterThenOrEqual($expected, $actual, $message = null) { 108 | return $this->scenario->runStep(new \Codeception\Step\Action('assertGreaterThenOrEqual', func_get_args())); 109 | } 110 | 111 | 112 | /** 113 | * [!] Method is generated. Documentation taken from corresponding module. 114 | * 115 | * Checks that expected is less than actual 116 | * 117 | * @param $expected 118 | * @param $actual 119 | * @param string $message 120 | * @see \Codeception\Module\Asserts::assertLessThan() 121 | */ 122 | public function assertLessThan($expected, $actual, $message = null) { 123 | return $this->scenario->runStep(new \Codeception\Step\Action('assertLessThan', func_get_args())); 124 | } 125 | 126 | 127 | /** 128 | * [!] Method is generated. Documentation taken from corresponding module. 129 | * 130 | * Checks that expected is less or equal than actual 131 | * 132 | * @param $expected 133 | * @param $actual 134 | * @param string $message 135 | * @see \Codeception\Module\Asserts::assertLessThanOrEqual() 136 | */ 137 | public function assertLessThanOrEqual($expected, $actual, $message = null) { 138 | return $this->scenario->runStep(new \Codeception\Step\Action('assertLessThanOrEqual', func_get_args())); 139 | } 140 | 141 | 142 | /** 143 | * [!] Method is generated. Documentation taken from corresponding module. 144 | * 145 | * Checks that haystack contains needle 146 | * 147 | * @param $needle 148 | * @param $haystack 149 | * @param string $message 150 | * @see \Codeception\Module\Asserts::assertContains() 151 | */ 152 | public function assertContains($needle, $haystack, $message = null) { 153 | return $this->scenario->runStep(new \Codeception\Step\Action('assertContains', func_get_args())); 154 | } 155 | 156 | 157 | /** 158 | * [!] Method is generated. Documentation taken from corresponding module. 159 | * 160 | * Checks that haystack doesn't contain needle. 161 | * 162 | * @param $needle 163 | * @param $haystack 164 | * @param string $message 165 | * @see \Codeception\Module\Asserts::assertNotContains() 166 | */ 167 | public function assertNotContains($needle, $haystack, $message = null) { 168 | return $this->scenario->runStep(new \Codeception\Step\Action('assertNotContains', func_get_args())); 169 | } 170 | 171 | 172 | /** 173 | * [!] Method is generated. Documentation taken from corresponding module. 174 | * 175 | * Checks that variable is empty. 176 | * 177 | * @param $actual 178 | * @param string $message 179 | * @see \Codeception\Module\Asserts::assertEmpty() 180 | */ 181 | public function assertEmpty($actual, $message = null) { 182 | return $this->scenario->runStep(new \Codeception\Step\Action('assertEmpty', func_get_args())); 183 | } 184 | 185 | 186 | /** 187 | * [!] Method is generated. Documentation taken from corresponding module. 188 | * 189 | * Checks that variable is not empty. 190 | * 191 | * @param $actual 192 | * @param string $message 193 | * @see \Codeception\Module\Asserts::assertNotEmpty() 194 | */ 195 | public function assertNotEmpty($actual, $message = null) { 196 | return $this->scenario->runStep(new \Codeception\Step\Action('assertNotEmpty', func_get_args())); 197 | } 198 | 199 | 200 | /** 201 | * [!] Method is generated. Documentation taken from corresponding module. 202 | * 203 | * Checks that variable is NULL 204 | * 205 | * @param $actual 206 | * @param string $message 207 | * @see \Codeception\Module\Asserts::assertNull() 208 | */ 209 | public function assertNull($actual, $message = null) { 210 | return $this->scenario->runStep(new \Codeception\Step\Action('assertNull', func_get_args())); 211 | } 212 | 213 | 214 | /** 215 | * [!] Method is generated. Documentation taken from corresponding module. 216 | * 217 | * Checks that variable is not NULL 218 | * 219 | * @param $actual 220 | * @param string $message 221 | * @see \Codeception\Module\Asserts::assertNotNull() 222 | */ 223 | public function assertNotNull($actual, $message = null) { 224 | return $this->scenario->runStep(new \Codeception\Step\Action('assertNotNull', func_get_args())); 225 | } 226 | 227 | 228 | /** 229 | * [!] Method is generated. Documentation taken from corresponding module. 230 | * 231 | * Checks that condition is positive. 232 | * 233 | * @param $condition 234 | * @param string $message 235 | * @see \Codeception\Module\Asserts::assertTrue() 236 | */ 237 | public function assertTrue($condition, $message = null) { 238 | return $this->scenario->runStep(new \Codeception\Step\Action('assertTrue', func_get_args())); 239 | } 240 | 241 | 242 | /** 243 | * [!] Method is generated. Documentation taken from corresponding module. 244 | * 245 | * Checks that condition is negative. 246 | * 247 | * @param $condition 248 | * @param string $message 249 | * @see \Codeception\Module\Asserts::assertFalse() 250 | */ 251 | public function assertFalse($condition, $message = null) { 252 | return $this->scenario->runStep(new \Codeception\Step\Action('assertFalse', func_get_args())); 253 | } 254 | 255 | 256 | /** 257 | * [!] Method is generated. Documentation taken from corresponding module. 258 | * 259 | * Fails the test with message. 260 | * 261 | * @param $message 262 | * @see \Codeception\Module\Asserts::fail() 263 | */ 264 | public function fail($message) { 265 | return $this->scenario->runStep(new \Codeception\Step\Action('fail', func_get_args())); 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /tests/unit/WhitelistTest.php: -------------------------------------------------------------------------------- 1 | assertTrue(Whitelist::get("127.0.0.1")->check()); 21 | $this->assertTrue(Whitelist::get("127.0.0.2")->check()); 22 | } catch (InvalidAuthException $e) { 23 | $this->assertNotEquals(401, $e->getCode()); 24 | } 25 | } 26 | 27 | public function testWhitelistFail() 28 | { 29 | try { 30 | $this->assertFalse(Whitelist::get("127.0.0.3")->check()); 31 | } catch (InvalidAuthException $e) { 32 | $this->assertEquals(401, $e->getCode()); 33 | } 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /tests/unit/_bootstrap.php: -------------------------------------------------------------------------------- 1 |