├── tests ├── migrations │ ├── .gitkeep │ └── m160614_100345_add_product_table_access_trait_test.php ├── .gitignore ├── unit │ ├── _bootstrap.php │ └── ModelTest.php ├── functional │ └── _bootstrap.php ├── unit.suite.yml ├── _support │ ├── UnitHelper.php │ ├── AcceptanceHelper.php │ ├── FunctionalHelper.php │ ├── Actions.php │ ├── UnitTester.php │ ├── AcceptanceTester.php │ ├── FunctionalTester.php │ └── _generated │ │ ├── UnitTesterActions.php │ │ ├── FunctionalTesterActions.php │ │ └── AcceptanceTesterActions.php ├── _config │ ├── unit.php │ ├── config.php │ └── local.php ├── functional.suite.yml ├── acceptance │ └── _bootstrap.php ├── _pages │ └── LoginPage.php ├── acceptance.suite.yml ├── _bootstrap.php ├── Makefile └── docker-compose.yml ├── .gitignore ├── db ├── exceptions │ └── UnsupportedDbException.php ├── mysql │ ├── templates │ │ └── file-migration.php │ ├── FileOverConnectionMigration.php │ └── FileMigration.php ├── postgre │ ├── templates │ │ └── file-migration.php │ └── FileMigration.php ├── behaviors │ └── HydratedAttributes.php └── helper │ └── CliHelper.php ├── codeception.yml ├── composer.json ├── .gitlab-ci.yml ├── README.md └── console └── controllers └── MysqlController.php /tests/migrations/.gitkeep: -------------------------------------------------------------------------------- 1 | * -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | _output 2 | 3 | tests/_output/* -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | runtime 3 | tests/runtime 4 | vendor 5 | -------------------------------------------------------------------------------- /tests/unit/_bootstrap.php: -------------------------------------------------------------------------------- 1 | 9 | */ 10 | class UnsupportedDbException extends \Exception 11 | { 12 | 13 | } -------------------------------------------------------------------------------- /tests/functional.suite.yml: -------------------------------------------------------------------------------- 1 | # Codeception Test Suite Configuration 2 | 3 | # suite for functional (integration) tests. 4 | # emulate web requests and make application process them. 5 | # Include one of framework modules (Symfony2, Yii2, Laravel5) to use it. 6 | 7 | class_name: FunctionalTester 8 | modules: 9 | enabled: [Filesystem, FunctionalHelper] 10 | -------------------------------------------------------------------------------- /tests/_config/config.php: -------------------------------------------------------------------------------- 1 | [ 7 | 'mailer' => [ 8 | 'useFileTransport' => true, 9 | ], 10 | 'request' => [ 11 | 'cookieValidationKey' => getenv('APP_COOKIE_VALIDATION_KEY') 12 | ], 13 | ], 14 | ]; 15 | -------------------------------------------------------------------------------- /tests/acceptance/_bootstrap.php: -------------------------------------------------------------------------------- 1 | 'app\controllers', 10 | ] 11 | ); 12 | 13 | new yii\web\Application($config); 14 | -------------------------------------------------------------------------------- /tests/_support/Actions.php: -------------------------------------------------------------------------------- 1 | 10 | 11 | use dmstr\db\mysql\FileMigration; 12 | 13 | class extends FileMigration 14 | { 15 | # create a sql file `.sql` or adjust and uncomment the following line, do not change this class name 16 | //public $file = 'custom-filename.sql'; 17 | } 18 | -------------------------------------------------------------------------------- /db/postgre/templates/file-migration.php: -------------------------------------------------------------------------------- 1 | 10 | 11 | use dmstr\db\postgre\FileMigration; 12 | 13 | class extends FileMigration 14 | { 15 | # create a sql file `.sql` or adjust and uncomment the following line, do not change this class name 16 | //public $file = 'custom-filename.sql'; 17 | } 18 | -------------------------------------------------------------------------------- /codeception.yml: -------------------------------------------------------------------------------- 1 | actor: Tester 2 | paths: 3 | tests: tests 4 | log: tests/_output 5 | data: tests/_data 6 | support: tests/_support 7 | envs: tests/_envs 8 | settings: 9 | bootstrap: _bootstrap.php 10 | colors: true 11 | memory_limit: 1024M 12 | extensions: 13 | enabled: 14 | - Codeception\Extension\RunFailed 15 | modules: 16 | config: 17 | Db: 18 | dsn: '' 19 | user: '' 20 | password: '' 21 | dump: tests/_data/dump.sql 22 | config: 23 | test_entry_url: http://web:80/index.php -------------------------------------------------------------------------------- /tests/_config/local.php: -------------------------------------------------------------------------------- 1 | [ 6 | '@dmstr/db' => '@vendor/dmstr/yii2-db', 7 | '@tests' => '@vendor/dmstr/yii2-db/tests' 8 | ], 9 | 'components' => [ 10 | 'db' => [ 11 | 'tablePrefix' => 'app_', 12 | ], 13 | 'urlManager' => [ 14 | 'enableDefaultLanguageUrlCode' => true, 15 | 'languages' => ['de', 'en', 'fr'] 16 | ], 17 | ], 18 | 'params' => [ 19 | 'yii.migrations' => [ 20 | '@vendor/dmstr/yii2-db/tests/migrations' 21 | ] 22 | ] 23 | ]; -------------------------------------------------------------------------------- /tests/_support/UnitTester.php: -------------------------------------------------------------------------------- 1 | actor->fillField('input[name="login-form[login]"]', $username); 22 | $this->actor->fillField('input[name="login-form[password]"]', $password); 23 | $this->actor->click('Sign in'); 24 | $this->actor->wait(3); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /tests/_support/AcceptanceTester.php: -------------------------------------------------------------------------------- 1 | =7.1", 20 | "mikehaertl/php-shellcommand": "1.*", 21 | "yiisoft/yii2": "2.*", 22 | "schmunk42/retry" : "*" 23 | }, 24 | "autoload": { 25 | "psr-4": { 26 | "dmstr\\db\\": "db/", 27 | "dmstr\\console\\": "console/" 28 | } 29 | }, 30 | "autoload-dev": { 31 | "psr-4": { 32 | "dmstr\\db\\tests\\": "db/tests/" 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tests/acceptance.suite.yml: -------------------------------------------------------------------------------- 1 | # Codeception Test Suite Configuration 2 | 3 | # suite for acceptance tests. 4 | # perform tests in browser using the WebDriver or PhpBrowser. 5 | # If you need both WebDriver and PHPBrowser tests - create a separate suite. 6 | 7 | class_name: AcceptanceTester 8 | modules: 9 | enabled: 10 | - WebDriver 11 | - AcceptanceHelper 12 | config: 13 | WebDriver: 14 | host: seleniumfirefox 15 | url: http://nginx:80/ 16 | browser: firefox 17 | port: 4444 18 | window_size: 1280x768 19 | env: 20 | chrome: 21 | modules: 22 | config: 23 | WebDriver: 24 | browser: 'chrome' 25 | host: seleniumchrome 26 | window_size: 1280x720 27 | firefox: 28 | # nothing changed -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | before_script: 2 | - export BUILD_PREFIX=build${CI_PIPELINE_ID} 3 | - export COMPOSE_PROJECT_NAME=${BUILD_PREFIX}yii2-db 4 | - cd tests 5 | 6 | stages: 7 | - test 8 | - report 9 | - cleanup 10 | 11 | test: 12 | stage: test 13 | script: 14 | - set +e 15 | - cd tests 16 | - make up setup 17 | - docker-compose run -e YII_ENV=test --rm phpfpm codecept run --html=_report.html; TESTS_EXIT_CODE=$? 18 | - set -e 19 | - mv _output /tmp/${BUILD_PREFIX} 20 | - exit $TESTS_EXIT_CODE 21 | 22 | report: 23 | stage: report 24 | script: 25 | - mv /tmp/${BUILD_PREFIX} _output 26 | artifacts: 27 | paths: 28 | - tests/_output/ 29 | when: always 30 | 31 | cleanup: 32 | stage: cleanup 33 | script: 34 | - docker-compose kill && docker-compose rm -fv 35 | - docker-compose down --rmi local --volumes 36 | when: always 37 | 38 | -------------------------------------------------------------------------------- /tests/_bootstrap.php: -------------------------------------------------------------------------------- 1 | 21 | */ 22 | class FileOverConnectionMigration extends Migration 23 | { 24 | public $file = null; 25 | public $mysqlExecutable = 'mysql'; 26 | 27 | public function init() 28 | { 29 | parent::init(); 30 | 31 | if ($this->file === null) { 32 | $reflection = new \ReflectionClass($this); 33 | $this->file = str_replace('.php', '.sql', $reflection->getFileName()); 34 | } else { 35 | $reflection = new \ReflectionClass($this); 36 | $this->file = dirname($reflection->getFileName()).DIRECTORY_SEPARATOR.$this->file; 37 | } 38 | 39 | if (!is_file($this->file)) { 40 | throw new Exception("File {$this->file} not found"); 41 | } 42 | } 43 | 44 | public function up() 45 | { 46 | $sql = file_get_contents($this->file); 47 | 48 | $this->db->createCommand($sql)->execute(); 49 | } 50 | 51 | public function down() 52 | { 53 | echo get_class($this) . " cannot be reverted.\n"; 54 | return false; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /db/postgre/FileMigration.php: -------------------------------------------------------------------------------- 1 | 19 | */ 20 | class FileMigration extends Migration 21 | { 22 | public $file = null; 23 | 24 | public function init() 25 | { 26 | parent::init(); 27 | 28 | if ($this->file === null) { 29 | $reflection = new \ReflectionClass($this); 30 | $this->file = str_replace('.php', '.sql', $reflection->getFileName()); 31 | } else { 32 | $reflection = new \ReflectionClass($this); 33 | $this->file = dirname($reflection->getFileName()).DIRECTORY_SEPARATOR.$this->file; 34 | } 35 | 36 | if (!is_file($this->file)) { 37 | throw new Exception("File {$this->file} not found"); 38 | } 39 | } 40 | 41 | /** 42 | * {@inheritdoc} 43 | */ 44 | public function up() 45 | { 46 | // Open connection if not opened already as we execute raw SQL on PDO we have no "autoconnect magick" here. 47 | if (!$this->db->isActive) { 48 | $this->db->open(); 49 | } 50 | 51 | $sql = file_get_contents($this->file); 52 | 53 | try { 54 | $result = $this->db->pdo->exec($sql); 55 | echo "Success exec: " . $this->file . "\n"; 56 | } catch (Exception $exception) { 57 | echo "\n-----\n" . $exception->getMessage() . "\n-----\n"; 58 | return false; 59 | } 60 | 61 | return true; 62 | } 63 | 64 | /** 65 | * {@inheritdoc} 66 | */ 67 | public function down() 68 | { 69 | echo $this::class . " cannot be reverted.\n"; 70 | return false; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /db/mysql/FileMigration.php: -------------------------------------------------------------------------------- 1 | 22 | */ 23 | class FileMigration extends Migration 24 | { 25 | 26 | public $file = null; 27 | public $mysqlExecutable = 'mysql'; 28 | public $mysqlOptions = []; 29 | 30 | public function init() 31 | { 32 | parent::init(); 33 | 34 | if ($this->file === null) { 35 | $reflection = new \ReflectionClass($this); 36 | $this->file = str_replace('.php', '.sql', $reflection->getFileName()); 37 | } else { 38 | $reflection = new \ReflectionClass($this); 39 | $this->file = dirname($reflection->getFileName()).DIRECTORY_SEPARATOR.$this->file; 40 | } 41 | 42 | if (!is_file($this->file)) { 43 | throw new Exception("File {$this->file} not found"); 44 | } 45 | } 46 | 47 | public function up() 48 | { 49 | 50 | $dsnOpts = CliHelper::getMysqlOptsFromDsn($this->db); 51 | 52 | $command = new Command($this->mysqlExecutable); 53 | $command->addArg('-h', $dsnOpts['host']); 54 | $command->addArg('-P', $dsnOpts['port']); 55 | $command->addArg('-u', $this->db->username); 56 | $command->addArg('--password=', $this->db->password); 57 | if ($this->db->charset) { 58 | $command->addArg('--default-character-set=', $this->db->charset); 59 | } 60 | 61 | foreach (CliHelper::getMysqlCliArgsFromPdo($this->db) as $opt => $value) { 62 | $command->addArg($opt, $value); 63 | } 64 | 65 | $cmd = $command->getExecCommand()." \"{$dsnOpts['db']}\" < \"{$this->file}\""; 66 | #echo " ".$cmd . "\n"; // TODO echo only with --verbose 67 | exec($cmd, $output, $return); 68 | 69 | if ($return !== 0) { 70 | //var_dump($output, $return); 71 | return false; 72 | } else { 73 | return true; 74 | } 75 | } 76 | 77 | public function down() 78 | { 79 | echo $this::className() . " cannot be reverted.\n"; 80 | return false; 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /db/behaviors/HydratedAttributes.php: -------------------------------------------------------------------------------- 1 | 21 | */ 22 | class HydratedAttributes extends Behavior 23 | { 24 | /** 25 | * @var column to use for array keys; has to be unique 26 | */ 27 | public $keyAttribute; 28 | 29 | private $_m; 30 | private $_d; 31 | 32 | public function getHydratedAttributes() 33 | { 34 | $attributes = $this->owner->attributes; 35 | $this->parseAttributesRecursive($this->owner, $attributes); 36 | return $attributes; 37 | } 38 | 39 | /** 40 | * @param $model The model which attributes should be parsed recursively 41 | * @param $attributes Variable which holds the attributes 42 | */ 43 | private function parseAttributesRecursive($model, &$attributes) 44 | { 45 | foreach ($model->relatedRecords AS $name => $relation) { 46 | if (is_array($relation)) { 47 | // many_many relation 48 | $attributes[$name] = []; 49 | foreach ($relation AS $rModel) { 50 | $d = $rModel->attributes; 51 | $this->parseAttributesRecursive($rModel, $d); 52 | // create index from column (Note: column has to be unique) 53 | if ($rModel->getBehavior('hydratedAttributes') && $rModel->keyAttribute) { 54 | if (isset($attributes[$name][$d[$rModel->keyAttribute]])) { 55 | throw new Exception("Index '{$d[$rModel->keyAttribute]}' not unique"); 56 | } else { 57 | $attributes[$name][$d[$rModel->keyAttribute]] = $d; 58 | } 59 | } else { 60 | $attributes[$name][] = $d; 61 | } 62 | } 63 | } else { 64 | if ($relation instanceof ActiveRecord) { 65 | // non-multiple 66 | $attributes[$name] = $relation->attributes; 67 | } else { 68 | $attributes[$name] = null; 69 | } 70 | } 71 | } 72 | } 73 | } -------------------------------------------------------------------------------- /db/helper/CliHelper.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | class CliHelper 25 | { 26 | public static function getMysqlCommand($mysqlExecutable = 'mysql', ?Connection $db = null) 27 | { 28 | if ($db === null) { 29 | throw new Exception('Invalid database config'); 30 | } 31 | 32 | $dsnOpts = CliHelper::getMysqlOptsFromDsn($db); 33 | 34 | $command = new Command($mysqlExecutable); 35 | $command->addArg('-h', $dsnOpts['host']); 36 | $command->addArg('-P', $dsnOpts['port']); 37 | $command->addArg('-u', $db->username); 38 | $command->addArg('--password=', $db->password); 39 | 40 | foreach (CliHelper::getMysqlCliArgsFromPdo($db) as $opt => $value) { 41 | $command->addArg($opt, $value); 42 | } 43 | 44 | return $command; 45 | } 46 | 47 | /** 48 | * parse dsn and return db host, db port and db name as array 49 | * 50 | * @param Connection $db 51 | * 52 | * @return array 53 | */ 54 | public static function getMysqlOptsFromDsn(Connection $db) 55 | { 56 | 57 | $cliArgs = [ 58 | 'host' => null, 59 | 'db' => null, 60 | 'port' => 3306, 61 | ]; 62 | 63 | preg_match('/host=([^;]*)/', $db->dsn, $hostMatches); 64 | $cliArgs['host'] = $hostMatches[1]; 65 | preg_match('/dbname=([^;]*)/', $db->dsn, $databaseMatches); 66 | $cliArgs['db'] = $databaseMatches[1]; 67 | preg_match('/port=([^;]*)/', $db->dsn, $portMatches); 68 | if (isset($portMatches[1])) { 69 | $cliArgs['port'] = $portMatches[1]; 70 | } 71 | 72 | return $cliArgs; 73 | } 74 | 75 | /** 76 | * map PDO Attributes to mysql cli args 77 | * 78 | * @param Connection $db 79 | * 80 | * @return array 81 | */ 82 | public static function getMysqlCliArgsFromPdo(Connection $db) 83 | { 84 | 85 | $optsMap = [ 86 | \PDO::MYSQL_ATTR_SSL_CAPATH => '--ssl-capath=', 87 | \PDO::MYSQL_ATTR_SSL_CA => '--ssl-ca=', 88 | \PDO::MYSQL_ATTR_SSL_CERT => '--ssl-cert=', 89 | \PDO::MYSQL_ATTR_SSL_KEY => '--ssl-key=', 90 | \PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT => '--ssl-verify-server-cert=', 91 | \PDO::MYSQL_ATTR_SSL_CIPHER => '--ssl-cipher=' 92 | ]; 93 | 94 | $cliArgs = []; 95 | if (!empty($db->attributes)) { 96 | foreach ($db->attributes as $key => $value) { 97 | if (array_key_exists($key, $optsMap)) { 98 | $cliArgs[$optsMap[$key]] = $value; 99 | } 100 | } 101 | } 102 | 103 | return $cliArgs; 104 | } 105 | 106 | } 107 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Yii 2 Database Toolkit 2 | ====================== 3 | 4 | [![Latest Stable Version](https://poser.pugx.org/dmstr/yii2-db/v/stable.svg)](https://packagist.org/packages/dmstr/yii2-db) 5 | [![Total Downloads](https://poser.pugx.org/dmstr/yii2-db/downloads.svg)](https://packagist.org/packages/dmstr/yii2-db) 6 | [![License](https://poser.pugx.org/dmstr/yii2-db/license.svg)](https://packagist.org/packages/dmstr/yii2-db) 7 | 8 | About 9 | ----- 10 | 11 | 12 | ### [dmstr\db\behaviors\HydratedAttributes](https://github.com/dmstr/yii2-db/blob/master/db/behaviors/HydratedAttributes.php) 13 | 14 | Retrieves all eager loaded attributes of a model including relations. Once the extension is installed, simply use it in your code by accessing the corresponding classes by their full namespaced path. 15 | 16 | ### [dmstr\db\mysql\FileMigration](https://github.com/dmstr/yii2-db/blob/master/db/mysql/FileMigration.php) 17 | 18 | runs database migrations from `sql` files 19 | 20 | 21 | - Generic database exentsions 22 | - Hydrated Attributes 23 | - Database extensions for MySQL 24 | - File Migration 25 | - Mysql dump/export/import console controller 26 | - RBAC migrations moved to https://github.com/dmstr/yii2-rbac-migration since 2.0.0 27 | - Active record access classes moved to https://github.com/dmstr/yii2-active-record-permissions since 2.0.0 28 | 29 | 30 | Installation 31 | ------------ 32 | 33 | The preferred way to install this extension is through [composer](http://getcomposer.org/download/). 34 | 35 | Either run 36 | 37 | ``` 38 | composer require --prefer-dist dmstr/yii2-db "*" 39 | ``` 40 | 41 | or add 42 | 43 | ``` 44 | "dmstr/yii2-db": "*" 45 | ``` 46 | 47 | to the require section of your `composer.json` file. 48 | 49 | Configuration 50 | ------------- 51 | 52 | ### [dmstr\console\controllers](https://github.com/dmstr/yii2-db/blob/master/console/controllers) 53 | 54 | Include it in your console configuration 55 | 56 | ``` 57 | 'controllerMap' => [ 58 | 'db' => [ 59 | 'class' => 'dmstr\console\controllers\MysqlController', 60 | 'noDataTables' => [ 61 | 'app_log', 62 | 'app_session', 63 | ] 64 | ], 65 | ], 66 | ``` 67 | 68 | Usage 69 | ----- 70 | 71 | ### Commands 72 | 73 | #### `yii migrate ...` 74 | 75 | Create a file migration class 76 | 77 | ``` 78 | yii migrate/create \ 79 | --templateFile='@vendor/dmstr/yii2-db/db/mysql/templates/file-migration.php' init_dump 80 | ``` 81 | 82 | 83 | #### `yii db ...` 84 | 85 | ``` 86 | DESCRIPTION 87 | 88 | MySQL database maintenance command for current (db) connection 89 | 90 | 91 | SUB-COMMANDS 92 | 93 | - db/create Create schema 94 | - db/destroy Remove schema 95 | - db/dump Dump schema (all tables) 96 | - db/export Export tables (INSERT only) 97 | - db/import Import from file to database and flush cache 98 | - db/index (default) Displays tables in database 99 | - db/wait-for-connection 100 | 101 | To see the detailed information about individual sub-commands, enter: 102 | 103 | yii help 104 | 105 | ``` 106 | 107 | 108 | Show help 109 | 110 | ``` 111 | yii help db 112 | ``` 113 | 114 | 115 | ### Examples 116 | 117 | Dry-run command (not available for all commands) 118 | 119 | ``` 120 | yii db/create root secret -n 121 | ``` 122 | 123 | Destroy database 124 | 125 | ``` 126 | yii db/destroy root secret 127 | ``` 128 | 129 | Dump all tables 130 | 131 | ``` 132 | yii db/dump -o /dumps 133 | ``` 134 | 135 | Dump from different connection, exclude logging tables 136 | 137 | ``` 138 | yii db/dump -o /dumps \ 139 | --db=dbReadonly \ 140 | --noDataTables=app_audit_data,app_audit_entry,app_audit_error,app_audit_javascript,app_audit_mail 141 | ``` 142 | 143 | Dump from secondary connection, import into primary (default) 144 | 145 | ``` 146 | yii db/dump -o /dumps \ 147 | --db=dbReadonly \ 148 | --noDataTables=app_audit_data,app_audit_entry,app_audit_error,app_audit_javascript,app_audit_mail \ 149 | | xargs yii db/import --interactive=0 150 | ``` 151 | 152 | 153 | --- 154 | 155 | Built by [dmstr](http://diemeisterei.de) 156 | -------------------------------------------------------------------------------- /tests/migrations/m160614_100345_add_product_table_access_trait_test.php: -------------------------------------------------------------------------------- 1 | createTable( 13 | $this->tableName, 14 | [ 15 | 'id' => $this->primaryKey(), 16 | 'title' => $this->string(255)->notNull(), 17 | 'access_domain' => $this->string(255), 18 | 'access_owner' => $this->integer(11), 19 | 'access_read' => $this->string(255), 20 | 'access_update' => $this->string(255), 21 | 'access_delete' => $this->string(255), 22 | ] 23 | ); 24 | 25 | /** 26 | * add a test user 27 | */ 28 | 29 | // Username: user 30 | // Password: user123 31 | $this->execute( 32 | " 33 | INSERT INTO `app_user` (`id`, `username`, `email`, `password_hash`, `auth_key`, `confirmed_at`, `unconfirmed_email`, `blocked_at`, `registration_ip`, `created_at`, `updated_at`, `flags`) 34 | VALUES 35 | (2, 'user', 'dbtest@h17n.de', '$2y$10$.4aD9IK6OxJGL2R0OU75deMBl9HQTQ3b0OVdzHpzZtR/BfF8EVYEa', '49p1_5UDnzhlS0hI8mqP_k4dNfm8YFqw', 1465899608, NULL, NULL, '192.168.99.1', 1465899608, 1465899608, 0); 36 | " 37 | ); 38 | 39 | /** 40 | * add test data 41 | */ 42 | 43 | // access All 44 | $this->insert( 45 | $this->tableName, 46 | [ 47 | 'title' => 'Product', 48 | 'access_domain' => 'en', 49 | 'access_owner' => '3', 50 | 'access_read' => '*', 51 | 'access_update' => '*', 52 | 'access_delete' => '*', 53 | ] 54 | ); 55 | 56 | // access read Editor 57 | $this->insert( 58 | $this->tableName, 59 | [ 60 | 'title' => 'Product', 61 | 'access_domain' => 'en', 62 | 'access_owner' => '3', 63 | 'access_read' => 'Editor', 64 | 'access_update' => '*', 65 | 'access_delete' => '*', 66 | ] 67 | ); 68 | 69 | // access update Editor 70 | $this->insert( 71 | $this->tableName, 72 | [ 73 | 'title' => 'Product', 74 | 'access_domain' => 'en', 75 | 'access_owner' => '3', 76 | 'access_read' => '*', 77 | 'access_update' => 'Editor', 78 | 'access_delete' => '*', 79 | ] 80 | ); 81 | 82 | // access delete Editor 83 | $this->insert( 84 | $this->tableName, 85 | [ 86 | 'title' => 'Product', 87 | 'access_domain' => 'en', 88 | 'access_owner' => '3', 89 | 'access_read' => '*', 90 | 'access_update' => '*', 91 | 'access_delete' => 'Editor', 92 | ] 93 | ); 94 | 95 | // access owner user 96 | $this->insert( 97 | $this->tableName, 98 | [ 99 | 'title' => 'Product', 100 | 'access_domain' => 'en', 101 | 'access_owner' => '2', 102 | 'access_read' => 'Supervisor', 103 | 'access_update' => 'Supervisor', 104 | 'access_delete' => 'Supervisor', 105 | ] 106 | ); 107 | 108 | // access domain de 109 | $this->insert( 110 | $this->tableName, 111 | [ 112 | 'title' => 'Product', 113 | 'access_domain' => 'de', 114 | 'access_owner' => '3', 115 | 'access_read' => '*', 116 | 'access_update' => '*', 117 | 'access_delete' => '*', 118 | ] 119 | ); 120 | // access domain 121 | $this->insert( 122 | $this->tableName, 123 | [ 124 | 'title' => 'Product', 125 | 'access_domain' => 'en', 126 | 'access_owner' => '3', 127 | 'access_read' => '*', 128 | 'access_update' => '*', 129 | 'access_delete' => '*', 130 | ] 131 | ); 132 | $this->insert( 133 | $this->tableName, 134 | [ 135 | 'title' => 'Product', 136 | 'access_domain' => 'de', 137 | 'access_owner' => '3', 138 | 'access_read' => 'Editor', 139 | 'access_update' => 'Supervisor', 140 | 'access_delete' => 'Supervisor', 141 | ] 142 | ); 143 | $this->insert( 144 | $this->tableName, 145 | [ 146 | 'title' => 'Product', 147 | 'access_domain' => 'fr', 148 | 'access_owner' => '3', 149 | 'access_read' => '*', 150 | 'access_update' => 'Supervisor', 151 | 'access_delete' => 'Supervisor', 152 | ] 153 | ); 154 | } 155 | 156 | public function safeDown() 157 | { 158 | $this->dropTable($this->tableName); 159 | $this->delete('app_user', ['id' => 2]); 160 | } 161 | } 162 | -------------------------------------------------------------------------------- /tests/unit/ModelTest.php: -------------------------------------------------------------------------------- 1 | 15 | */ 16 | class AccessTrait extends \yii\codeception\DbTestCase 17 | { 18 | public $appConfig = '/app/vendor/dmstr/yii2-db/tests/_config/unit.php'; 19 | 20 | /** 21 | * Log in with username 22 | * 23 | * @param $username 24 | */ 25 | private function login($username) 26 | { 27 | $user = User::findOne(['username' => $username]); 28 | \Yii::$app->user->login($user); 29 | } 30 | 31 | /** 32 | * Logout user and destroy session 33 | */ 34 | private function logout() 35 | { 36 | \Yii::$app->user->logout(); 37 | } 38 | 39 | /** 40 | * Test access read 41 | */ 42 | public function testAccessRead() 43 | { 44 | // check 'en' records as public 45 | \Yii::$app->language = 'en'; 46 | 47 | $authManager = \Yii::$app->authManager; 48 | 49 | // try to find public accessible products 50 | // expect 4 51 | $products = Product::find()->all(); 52 | $this->assertEquals(4, count($products), 'Public: cannot read the 4 expected products'); 53 | 54 | // try to find accessible products for user #2 55 | // expect 5 56 | $this->login('user'); 57 | $products = Product::find()->all(); 58 | $this->assertEquals(5, count($products), 'User: cannot read the 5 expected products'); 59 | 60 | // assign Editor role to user #2 61 | $authManager->assign($authManager->getRole('Editor'), \Yii::$app->user->id); 62 | // try to find accessible products for user #2 as Editor 63 | // expect 6 64 | $products = Product::find()->all(); 65 | $this->assertEquals(6, count($products), 'User as Editor: cannot read the 6 expected products'); 66 | $authManager->revoke($authManager->getRole('Editor'), \Yii::$app->user->id); 67 | 68 | $this->logout(); 69 | } 70 | 71 | /** 72 | * Test access update 73 | */ 74 | public function testAccessUpdate() 75 | { 76 | $authManager = \Yii::$app->authManager; 77 | 78 | // try to update product #1 as public 79 | // expect true 80 | $product = Product::findOne(1); 81 | $product->title = 'Product updated by public user'; 82 | $this->assertTrue($product->save(), 'Public: cannot update product #1'); 83 | 84 | // try to update product #3 as public 85 | // expect false 86 | $product = Product::findOne(3); 87 | $product->title = 'Product updated by public user'; 88 | $this->assertFalse($product->save(), 'Public: should not be able to update product #3'); 89 | 90 | // Login as user #2 91 | $this->login('user'); 92 | 93 | // try to update product #3 as user #2 94 | // expect false 95 | $product = Product::findOne(3); 96 | $product->title = 'Product updated by user #2'; 97 | $this->assertFalse($product->save(), 'User: should not be able to update product #3'); 98 | 99 | // assign Editor role to user #2 100 | $authManager->assign($authManager->getRole('Editor'), \Yii::$app->user->id); 101 | // try to update product #3 as user #2 102 | // expect true 103 | $product = Product::findOne(3); 104 | $product->title = 'Product updated by user #2 as Editor'; 105 | $this->assertTrue($product->save(), 'User: should not be able to update product #3'); 106 | $authManager->revoke($authManager->getRole('Editor'), \Yii::$app->user->id); 107 | 108 | $this->logout(); 109 | } 110 | 111 | 112 | /** 113 | * Test access owner 114 | */ 115 | public function testAccessOwner() 116 | { 117 | // try to find, update and delete product #5 with user #2 118 | $this->login('user'); 119 | 120 | // read expect true 121 | $product = Product::findOne(5); 122 | $this->assertEquals(1, count($product), 'User: cannot read product #5 as owner'); 123 | 124 | // update expect true 125 | $product->title = 'Product updated by user #2 with only owner access'; 126 | $this->assertTrue($product->save(), 'User: should be able to update product #5'); 127 | 128 | // delete expect equals 1 deleted row 129 | $product = Product::findOne(5); 130 | $this->assertEquals(1, $product->delete(), 'User: should be able to delete product #5'); 131 | 132 | // re-add product #5 133 | $restoreProduct = new Product(); 134 | $restoreProduct->id = 5; 135 | $restoreProduct->title = 'Product'; 136 | $restoreProduct->access_domain = 'en'; 137 | $restoreProduct->access_read = 'Supervisor'; 138 | $restoreProduct->access_update = 'Supervisor'; 139 | $restoreProduct->access_delete = 'Supervisor'; 140 | $restoreProduct->save(); 141 | 142 | $this->logout(); 143 | } 144 | 145 | /** 146 | * Test access domain 147 | */ 148 | public function testAccessDomain() 149 | { 150 | // check 'de' records as public 151 | \Yii::$app->language = 'de'; 152 | $authManager = \Yii::$app->authManager; 153 | 154 | // expect 1 155 | $products = Product::find()->all(); 156 | $this->assertEquals(1, count($products), 'Public: cannot read the 1 expected product for "de"'); 157 | 158 | // check 'de' records as user as Editor 159 | $this->login('user'); 160 | // assign Editor role to user #2 161 | $authManager->assign($authManager->getRole('Editor'), \Yii::$app->user->id); 162 | $products = Product::find()->all(); 163 | $this->assertEquals(2, count($products), 'User: cannot read the 2 expected products for "de"'); 164 | $authManager->revoke($authManager->getRole('Editor'), \Yii::$app->user->id); 165 | $this->logout(); 166 | 167 | // check 'en' records as public 168 | \Yii::$app->language = 'en'; 169 | 170 | // expect 4 171 | $products = Product::find()->all(); 172 | $this->assertEquals(4, count($products), 'Public: cannot read the 4 expected products for "en"'); 173 | 174 | // check 'en' records as public 175 | \Yii::$app->language = 'fr'; 176 | 177 | // expect 1 178 | $products = Product::find()->all(); 179 | $this->assertEquals(1, count($products), 'Public: cannot read the 1 expected product for "fr"'); 180 | } 181 | 182 | /** 183 | * Test access delete 184 | */ 185 | public function testAccessDelete() 186 | { 187 | // check 'en' records 188 | \Yii::$app->language = 'en'; 189 | $authManager = \Yii::$app->authManager; 190 | 191 | // try to delete product #4 192 | // expect not equals 1 deleted row 193 | $product = Product::findOne(4); 194 | $this->assertNotEquals(1, $product->delete(), 'Public: should not be able to delete product #4'); 195 | 196 | // try to delete product #4 with user #2 197 | // expect not equals 1 deleted row 198 | $this->login('user'); 199 | $product = Product::findOne(4); 200 | $this->assertNotEquals(1, $product->delete(), 'User: should not be able to delete product #4'); 201 | 202 | // assign Editor role to user #2 203 | $authManager->assign($authManager->getRole('Editor'), \Yii::$app->user->id); 204 | // try to delete product #4 with user #2 as Editor 205 | // expect true 206 | $product = Product::findOne(4); 207 | $this->assertEquals(1, $product->delete(), 'User: should be able to update product #4 as "Editor"'); 208 | $authManager->revoke($authManager->getRole('Editor'), \Yii::$app->user->id); 209 | 210 | $this->logout(); 211 | 212 | // re-add product #4 213 | $this->login('admin'); 214 | $restoreProduct = new Product(); 215 | $restoreProduct->id = 4; 216 | $restoreProduct->title = 'Product'; 217 | $restoreProduct->access_domain = 'en'; 218 | $restoreProduct->access_read = '*'; 219 | $restoreProduct->access_update = '*'; 220 | $restoreProduct->access_delete = 'Editor'; 221 | $restoreProduct->save(); 222 | 223 | $this->logout(); 224 | } 225 | } 226 | 227 | /** 228 | * This is the model class for table "product". 229 | * 230 | * @property integer $id 231 | * @property string $title 232 | * 233 | */ 234 | class Product extends ActiveRecord 235 | { 236 | use ActiveRecordAccessTrait; 237 | 238 | /** 239 | * @inheritdoc 240 | */ 241 | public static function tableName() 242 | { 243 | return 'product'; 244 | } 245 | 246 | /** 247 | * @inheritdoc 248 | */ 249 | public function rules() 250 | { 251 | return [ 252 | [['title'], 'required'], 253 | [['title'], 'string', 'max' => 255], 254 | ]; 255 | } 256 | 257 | /** 258 | * @inheritdoc 259 | */ 260 | public function attributeLabels() 261 | { 262 | return [ 263 | 'id' => Yii::t('test-yii2-db', 'ID'), 264 | 'title' => Yii::t('test-yii2-db', 'Title'), 265 | ]; 266 | } 267 | } 268 | -------------------------------------------------------------------------------- /tests/_support/_generated/UnitTesterActions.php: -------------------------------------------------------------------------------- 1 | getScenario()->runStep(new \Codeception\Step\Action('assertEquals', func_get_args())); 31 | } 32 | 33 | 34 | /** 35 | * [!] Method is generated. Documentation taken from corresponding module. 36 | * 37 | * Checks that two variables are not equal 38 | * 39 | * @param $expected 40 | * @param $actual 41 | * @param string $message 42 | * @see \Codeception\Module\Asserts::assertNotEquals() 43 | */ 44 | public function assertNotEquals($expected, $actual, $message = null) { 45 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotEquals', func_get_args())); 46 | } 47 | 48 | 49 | /** 50 | * [!] Method is generated. Documentation taken from corresponding module. 51 | * 52 | * Checks that two variables are same 53 | * 54 | * @param $expected 55 | * @param $actual 56 | * @param string $message 57 | * @see \Codeception\Module\Asserts::assertSame() 58 | */ 59 | public function assertSame($expected, $actual, $message = null) { 60 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertSame', func_get_args())); 61 | } 62 | 63 | 64 | /** 65 | * [!] Method is generated. Documentation taken from corresponding module. 66 | * 67 | * Checks that two variables are not same 68 | * 69 | * @param $expected 70 | * @param $actual 71 | * @param string $message 72 | * @see \Codeception\Module\Asserts::assertNotSame() 73 | */ 74 | public function assertNotSame($expected, $actual, $message = null) { 75 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotSame', func_get_args())); 76 | } 77 | 78 | 79 | /** 80 | * [!] Method is generated. Documentation taken from corresponding module. 81 | * 82 | * Checks that actual is greater than expected 83 | * 84 | * @param $expected 85 | * @param $actual 86 | * @param string $message 87 | * @see \Codeception\Module\Asserts::assertGreaterThan() 88 | */ 89 | public function assertGreaterThan($expected, $actual, $message = null) { 90 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertGreaterThan', func_get_args())); 91 | } 92 | 93 | 94 | /** 95 | * [!] Method is generated. Documentation taken from corresponding module. 96 | * 97 | * @deprecated 98 | * @see \Codeception\Module\Asserts::assertGreaterThen() 99 | */ 100 | public function assertGreaterThen($expected, $actual, $message = null) { 101 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertGreaterThen', func_get_args())); 102 | } 103 | 104 | 105 | /** 106 | * [!] Method is generated. Documentation taken from corresponding module. 107 | * 108 | * Checks that actual is greater or equal than expected 109 | * 110 | * @param $expected 111 | * @param $actual 112 | * @param string $message 113 | * @see \Codeception\Module\Asserts::assertGreaterThanOrEqual() 114 | */ 115 | public function assertGreaterThanOrEqual($expected, $actual, $message = null) { 116 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertGreaterThanOrEqual', func_get_args())); 117 | } 118 | 119 | 120 | /** 121 | * [!] Method is generated. Documentation taken from corresponding module. 122 | * 123 | * @deprecated 124 | * @see \Codeception\Module\Asserts::assertGreaterThenOrEqual() 125 | */ 126 | public function assertGreaterThenOrEqual($expected, $actual, $message = null) { 127 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertGreaterThenOrEqual', func_get_args())); 128 | } 129 | 130 | 131 | /** 132 | * [!] Method is generated. Documentation taken from corresponding module. 133 | * 134 | * Checks that actual is less than expected 135 | * 136 | * @param $expected 137 | * @param $actual 138 | * @param string $message 139 | * @see \Codeception\Module\Asserts::assertLessThan() 140 | */ 141 | public function assertLessThan($expected, $actual, $message = null) { 142 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertLessThan', func_get_args())); 143 | } 144 | 145 | 146 | /** 147 | * [!] Method is generated. Documentation taken from corresponding module. 148 | * 149 | * Checks that actual is less or equal than expected 150 | * 151 | * @param $expected 152 | * @param $actual 153 | * @param string $message 154 | * @see \Codeception\Module\Asserts::assertLessThanOrEqual() 155 | */ 156 | public function assertLessThanOrEqual($expected, $actual, $message = null) { 157 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertLessThanOrEqual', func_get_args())); 158 | } 159 | 160 | 161 | /** 162 | * [!] Method is generated. Documentation taken from corresponding module. 163 | * 164 | * Checks that haystack contains needle 165 | * 166 | * @param $needle 167 | * @param $haystack 168 | * @param string $message 169 | * @see \Codeception\Module\Asserts::assertContains() 170 | */ 171 | public function assertContains($needle, $haystack, $message = null) { 172 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertContains', func_get_args())); 173 | } 174 | 175 | 176 | /** 177 | * [!] Method is generated. Documentation taken from corresponding module. 178 | * 179 | * Checks that haystack doesn't contain needle. 180 | * 181 | * @param $needle 182 | * @param $haystack 183 | * @param string $message 184 | * @see \Codeception\Module\Asserts::assertNotContains() 185 | */ 186 | public function assertNotContains($needle, $haystack, $message = null) { 187 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotContains', func_get_args())); 188 | } 189 | 190 | 191 | /** 192 | * [!] Method is generated. Documentation taken from corresponding module. 193 | * 194 | * Checks that string match with pattern 195 | * 196 | * @param string $pattern 197 | * @param string $string 198 | * @param string $message 199 | * @see \Codeception\Module\Asserts::assertRegExp() 200 | */ 201 | public function assertRegExp($pattern, $string, $message = null) { 202 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertRegExp', func_get_args())); 203 | } 204 | 205 | 206 | /** 207 | * [!] Method is generated. Documentation taken from corresponding module. 208 | * 209 | * Checks that string not match with pattern 210 | * 211 | * @param string $pattern 212 | * @param string $string 213 | * @param string $message 214 | * @see \Codeception\Module\Asserts::assertNotRegExp() 215 | */ 216 | public function assertNotRegExp($pattern, $string, $message = null) { 217 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotRegExp', func_get_args())); 218 | } 219 | 220 | 221 | /** 222 | * [!] Method is generated. Documentation taken from corresponding module. 223 | * 224 | * Checks that variable is empty. 225 | * 226 | * @param $actual 227 | * @param string $message 228 | * @see \Codeception\Module\Asserts::assertEmpty() 229 | */ 230 | public function assertEmpty($actual, $message = null) { 231 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertEmpty', func_get_args())); 232 | } 233 | 234 | 235 | /** 236 | * [!] Method is generated. Documentation taken from corresponding module. 237 | * 238 | * Checks that variable is not empty. 239 | * 240 | * @param $actual 241 | * @param string $message 242 | * @see \Codeception\Module\Asserts::assertNotEmpty() 243 | */ 244 | public function assertNotEmpty($actual, $message = null) { 245 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotEmpty', func_get_args())); 246 | } 247 | 248 | 249 | /** 250 | * [!] Method is generated. Documentation taken from corresponding module. 251 | * 252 | * Checks that variable is NULL 253 | * 254 | * @param $actual 255 | * @param string $message 256 | * @see \Codeception\Module\Asserts::assertNull() 257 | */ 258 | public function assertNull($actual, $message = null) { 259 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNull', func_get_args())); 260 | } 261 | 262 | 263 | /** 264 | * [!] Method is generated. Documentation taken from corresponding module. 265 | * 266 | * Checks that variable is not NULL 267 | * 268 | * @param $actual 269 | * @param string $message 270 | * @see \Codeception\Module\Asserts::assertNotNull() 271 | */ 272 | public function assertNotNull($actual, $message = null) { 273 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertNotNull', func_get_args())); 274 | } 275 | 276 | 277 | /** 278 | * [!] Method is generated. Documentation taken from corresponding module. 279 | * 280 | * Checks that condition is positive. 281 | * 282 | * @param $condition 283 | * @param string $message 284 | * @see \Codeception\Module\Asserts::assertTrue() 285 | */ 286 | public function assertTrue($condition, $message = null) { 287 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertTrue', func_get_args())); 288 | } 289 | 290 | 291 | /** 292 | * [!] Method is generated. Documentation taken from corresponding module. 293 | * 294 | * Checks that condition is negative. 295 | * 296 | * @param $condition 297 | * @param string $message 298 | * @see \Codeception\Module\Asserts::assertFalse() 299 | */ 300 | public function assertFalse($condition, $message = null) { 301 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFalse', func_get_args())); 302 | } 303 | 304 | 305 | /** 306 | * [!] Method is generated. Documentation taken from corresponding module. 307 | * 308 | * Checks if file exists 309 | * 310 | * @param string $filename 311 | * @param string $message 312 | * @see \Codeception\Module\Asserts::assertFileExists() 313 | */ 314 | public function assertFileExists($filename, $message = null) { 315 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileExists', func_get_args())); 316 | } 317 | 318 | 319 | /** 320 | * [!] Method is generated. Documentation taken from corresponding module. 321 | * 322 | * Checks if file doesn't exist 323 | * 324 | * @param string $filename 325 | * @param string $message 326 | * @see \Codeception\Module\Asserts::assertFileNotExists() 327 | */ 328 | public function assertFileNotExists($filename, $message = null) { 329 | return $this->getScenario()->runStep(new \Codeception\Step\Action('assertFileNotExists', func_get_args())); 330 | } 331 | 332 | 333 | /** 334 | * [!] Method is generated. Documentation taken from corresponding module. 335 | * 336 | * Fails the test with message. 337 | * 338 | * @param $message 339 | * @see \Codeception\Module\Asserts::fail() 340 | */ 341 | public function fail($message) { 342 | return $this->getScenario()->runStep(new \Codeception\Step\Action('fail', func_get_args())); 343 | } 344 | } 345 | -------------------------------------------------------------------------------- /tests/_support/_generated/FunctionalTesterActions.php: -------------------------------------------------------------------------------- 1 | getScenario()->runStep(new \Codeception\Step\Condition('amInPath', func_get_args())); 30 | } 31 | 32 | 33 | /** 34 | * [!] Method is generated. Documentation taken from corresponding module. 35 | * 36 | * Opens a file and stores it's content. 37 | * 38 | * Usage: 39 | * 40 | * ``` php 41 | * openFile('composer.json'); 43 | * $I->seeInThisFile('codeception/codeception'); 44 | * ?> 45 | * ``` 46 | * 47 | * @param $filename 48 | * @see \Codeception\Module\Filesystem::openFile() 49 | */ 50 | public function openFile($filename) { 51 | return $this->getScenario()->runStep(new \Codeception\Step\Action('openFile', func_get_args())); 52 | } 53 | 54 | 55 | /** 56 | * [!] Method is generated. Documentation taken from corresponding module. 57 | * 58 | * Deletes a file 59 | * 60 | * ``` php 61 | * deleteFile('composer.lock'); 63 | * ?> 64 | * ``` 65 | * 66 | * @param $filename 67 | * @see \Codeception\Module\Filesystem::deleteFile() 68 | */ 69 | public function deleteFile($filename) { 70 | return $this->getScenario()->runStep(new \Codeception\Step\Action('deleteFile', func_get_args())); 71 | } 72 | 73 | 74 | /** 75 | * [!] Method is generated. Documentation taken from corresponding module. 76 | * 77 | * Deletes directory with all subdirectories 78 | * 79 | * ``` php 80 | * deleteDir('vendor'); 82 | * ?> 83 | * ``` 84 | * 85 | * @param $dirname 86 | * @see \Codeception\Module\Filesystem::deleteDir() 87 | */ 88 | public function deleteDir($dirname) { 89 | return $this->getScenario()->runStep(new \Codeception\Step\Action('deleteDir', func_get_args())); 90 | } 91 | 92 | 93 | /** 94 | * [!] Method is generated. Documentation taken from corresponding module. 95 | * 96 | * Copies directory with all contents 97 | * 98 | * ``` php 99 | * copyDir('vendor','old_vendor'); 101 | * ?> 102 | * ``` 103 | * 104 | * @param $src 105 | * @param $dst 106 | * @see \Codeception\Module\Filesystem::copyDir() 107 | */ 108 | public function copyDir($src, $dst) { 109 | return $this->getScenario()->runStep(new \Codeception\Step\Action('copyDir', func_get_args())); 110 | } 111 | 112 | 113 | /** 114 | * [!] Method is generated. Documentation taken from corresponding module. 115 | * 116 | * Checks If opened file has `text` in it. 117 | * 118 | * Usage: 119 | * 120 | * ``` php 121 | * openFile('composer.json'); 123 | * $I->seeInThisFile('codeception/codeception'); 124 | * ?> 125 | * ``` 126 | * 127 | * @param $text 128 | * Conditional Assertion: Test won't be stopped on fail 129 | * @see \Codeception\Module\Filesystem::seeInThisFile() 130 | */ 131 | public function canSeeInThisFile($text) { 132 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInThisFile', func_get_args())); 133 | } 134 | /** 135 | * [!] Method is generated. Documentation taken from corresponding module. 136 | * 137 | * Checks If opened file has `text` in it. 138 | * 139 | * Usage: 140 | * 141 | * ``` php 142 | * openFile('composer.json'); 144 | * $I->seeInThisFile('codeception/codeception'); 145 | * ?> 146 | * ``` 147 | * 148 | * @param $text 149 | * @see \Codeception\Module\Filesystem::seeInThisFile() 150 | */ 151 | public function seeInThisFile($text) { 152 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInThisFile', func_get_args())); 153 | } 154 | 155 | 156 | /** 157 | * [!] Method is generated. Documentation taken from corresponding module. 158 | * 159 | * Checks If opened file has the `number` of new lines. 160 | * 161 | * Usage: 162 | * 163 | * ``` php 164 | * openFile('composer.json'); 166 | * $I->seeNumberNewLines(5); 167 | * ?> 168 | * ``` 169 | * 170 | * @param int $number New lines 171 | * Conditional Assertion: Test won't be stopped on fail 172 | * @see \Codeception\Module\Filesystem::seeNumberNewLines() 173 | */ 174 | public function canSeeNumberNewLines($number) { 175 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeNumberNewLines', func_get_args())); 176 | } 177 | /** 178 | * [!] Method is generated. Documentation taken from corresponding module. 179 | * 180 | * Checks If opened file has the `number` of new lines. 181 | * 182 | * Usage: 183 | * 184 | * ``` php 185 | * openFile('composer.json'); 187 | * $I->seeNumberNewLines(5); 188 | * ?> 189 | * ``` 190 | * 191 | * @param int $number New lines 192 | * @see \Codeception\Module\Filesystem::seeNumberNewLines() 193 | */ 194 | public function seeNumberNewLines($number) { 195 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeNumberNewLines', func_get_args())); 196 | } 197 | 198 | 199 | /** 200 | * [!] Method is generated. Documentation taken from corresponding module. 201 | * 202 | * Checks the strict matching of file contents. 203 | * Unlike `seeInThisFile` will fail if file has something more than expected lines. 204 | * Better to use with HEREDOC strings. 205 | * Matching is done after removing "\r" chars from file content. 206 | * 207 | * ``` php 208 | * openFile('process.pid'); 210 | * $I->seeFileContentsEqual('3192'); 211 | * ?> 212 | * ``` 213 | * 214 | * @param $text 215 | * Conditional Assertion: Test won't be stopped on fail 216 | * @see \Codeception\Module\Filesystem::seeFileContentsEqual() 217 | */ 218 | public function canSeeFileContentsEqual($text) { 219 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeFileContentsEqual', func_get_args())); 220 | } 221 | /** 222 | * [!] Method is generated. Documentation taken from corresponding module. 223 | * 224 | * Checks the strict matching of file contents. 225 | * Unlike `seeInThisFile` will fail if file has something more than expected lines. 226 | * Better to use with HEREDOC strings. 227 | * Matching is done after removing "\r" chars from file content. 228 | * 229 | * ``` php 230 | * openFile('process.pid'); 232 | * $I->seeFileContentsEqual('3192'); 233 | * ?> 234 | * ``` 235 | * 236 | * @param $text 237 | * @see \Codeception\Module\Filesystem::seeFileContentsEqual() 238 | */ 239 | public function seeFileContentsEqual($text) { 240 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeFileContentsEqual', func_get_args())); 241 | } 242 | 243 | 244 | /** 245 | * [!] Method is generated. Documentation taken from corresponding module. 246 | * 247 | * Checks If opened file doesn't contain `text` in it 248 | * 249 | * ``` php 250 | * openFile('composer.json'); 252 | * $I->dontSeeInThisFile('codeception/codeception'); 253 | * ?> 254 | * ``` 255 | * 256 | * @param $text 257 | * Conditional Assertion: Test won't be stopped on fail 258 | * @see \Codeception\Module\Filesystem::dontSeeInThisFile() 259 | */ 260 | public function cantSeeInThisFile($text) { 261 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInThisFile', func_get_args())); 262 | } 263 | /** 264 | * [!] Method is generated. Documentation taken from corresponding module. 265 | * 266 | * Checks If opened file doesn't contain `text` in it 267 | * 268 | * ``` php 269 | * openFile('composer.json'); 271 | * $I->dontSeeInThisFile('codeception/codeception'); 272 | * ?> 273 | * ``` 274 | * 275 | * @param $text 276 | * @see \Codeception\Module\Filesystem::dontSeeInThisFile() 277 | */ 278 | public function dontSeeInThisFile($text) { 279 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInThisFile', func_get_args())); 280 | } 281 | 282 | 283 | /** 284 | * [!] Method is generated. Documentation taken from corresponding module. 285 | * 286 | * Deletes a file 287 | * @see \Codeception\Module\Filesystem::deleteThisFile() 288 | */ 289 | public function deleteThisFile() { 290 | return $this->getScenario()->runStep(new \Codeception\Step\Action('deleteThisFile', func_get_args())); 291 | } 292 | 293 | 294 | /** 295 | * [!] Method is generated. Documentation taken from corresponding module. 296 | * 297 | * Checks if file exists in path. 298 | * Opens a file when it's exists 299 | * 300 | * ``` php 301 | * seeFileFound('UserModel.php','app/models'); 303 | * ?> 304 | * ``` 305 | * 306 | * @param $filename 307 | * @param string $path 308 | * Conditional Assertion: Test won't be stopped on fail 309 | * @see \Codeception\Module\Filesystem::seeFileFound() 310 | */ 311 | public function canSeeFileFound($filename, $path = null) { 312 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeFileFound', func_get_args())); 313 | } 314 | /** 315 | * [!] Method is generated. Documentation taken from corresponding module. 316 | * 317 | * Checks if file exists in path. 318 | * Opens a file when it's exists 319 | * 320 | * ``` php 321 | * seeFileFound('UserModel.php','app/models'); 323 | * ?> 324 | * ``` 325 | * 326 | * @param $filename 327 | * @param string $path 328 | * @see \Codeception\Module\Filesystem::seeFileFound() 329 | */ 330 | public function seeFileFound($filename, $path = null) { 331 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeFileFound', func_get_args())); 332 | } 333 | 334 | 335 | /** 336 | * [!] Method is generated. Documentation taken from corresponding module. 337 | * 338 | * Checks if file does not exist in path 339 | * 340 | * @param $filename 341 | * @param string $path 342 | * Conditional Assertion: Test won't be stopped on fail 343 | * @see \Codeception\Module\Filesystem::dontSeeFileFound() 344 | */ 345 | public function cantSeeFileFound($filename, $path = null) { 346 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeFileFound', func_get_args())); 347 | } 348 | /** 349 | * [!] Method is generated. Documentation taken from corresponding module. 350 | * 351 | * Checks if file does not exist in path 352 | * 353 | * @param $filename 354 | * @param string $path 355 | * @see \Codeception\Module\Filesystem::dontSeeFileFound() 356 | */ 357 | public function dontSeeFileFound($filename, $path = null) { 358 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeFileFound', func_get_args())); 359 | } 360 | 361 | 362 | /** 363 | * [!] Method is generated. Documentation taken from corresponding module. 364 | * 365 | * Erases directory contents 366 | * 367 | * ``` php 368 | * cleanDir('logs'); 370 | * ?> 371 | * ``` 372 | * 373 | * @param $dirname 374 | * @see \Codeception\Module\Filesystem::cleanDir() 375 | */ 376 | public function cleanDir($dirname) { 377 | return $this->getScenario()->runStep(new \Codeception\Step\Action('cleanDir', func_get_args())); 378 | } 379 | 380 | 381 | /** 382 | * [!] Method is generated. Documentation taken from corresponding module. 383 | * 384 | * Saves contents to file 385 | * 386 | * @param $filename 387 | * @param $contents 388 | * @see \Codeception\Module\Filesystem::writeToFile() 389 | */ 390 | public function writeToFile($filename, $contents) { 391 | return $this->getScenario()->runStep(new \Codeception\Step\Action('writeToFile', func_get_args())); 392 | } 393 | } 394 | -------------------------------------------------------------------------------- /console/controllers/MysqlController.php: -------------------------------------------------------------------------------- 1 | 'verbose', 114 | 'n' => 'dryRun', 115 | 'o' => 'outputPath', 116 | 'I' => 'includeTables', 117 | 'X' => 'excludeTables', 118 | ] 119 | ); 120 | } 121 | 122 | public function beforeAction($action) 123 | { 124 | $db = \Yii::$app->get($this->db); 125 | $this->stdout($db->dsn . PHP_EOL, Console::FG_YELLOW); 126 | return parent::beforeAction($action); 127 | } 128 | 129 | public function afterAction($action, $result) 130 | { 131 | $this->stdout(PHP_EOL); 132 | return parent::afterAction($action, $result); 133 | } 134 | 135 | /** 136 | * Displays tables in database 137 | * @throws Exception 138 | */ 139 | public function actionIndex() 140 | { 141 | $db = \Yii::$app->get($this->db); 142 | $opts = CliHelper::getMysqlOptsFromDsn($db); 143 | $cmd = CliHelper::getMysqlCommand('mysqlshow', $db); 144 | 145 | $cmd->addArg($opts['db']); 146 | 147 | $this->stdout($this->execute($cmd)); 148 | } 149 | 150 | 151 | public function actionWaitForConnection($user = null, $password = null) 152 | { 153 | $db = \Yii::$app->get($this->db); 154 | $opts = CliHelper::getMysqlOptsFromDsn($db); 155 | // use dsn without database 156 | $dsn = 'mysql:host=' . $opts['host'] . ';port=' . $opts['port']; 157 | 158 | if (!$user) { 159 | $user = $db->username; 160 | } 161 | if (!$password) { 162 | $password = $db->password; 163 | } 164 | 165 | // trying to connect to database with PDO (20 times, interval 1 second) 166 | $this->stdout( 167 | "Checking database connection on DSN '{$dsn}' with user '{$user}'" 168 | ); 169 | 170 | try { 171 | // retry an operation up to 20 times 172 | $pdo = \igorw\retry( 173 | $this->mysqlRetryMaxCount, 174 | function () use ($dsn, $user, $password) { 175 | $this->stdout('.'); 176 | sleep($this->mysqlRetryTimeout); 177 | return new \PDO($dsn, $user, $password); 178 | } 179 | ); 180 | } catch (FailingTooHardException $e) { 181 | $this->stderr("\n\nError: Unable to connect to database '" . $e->getMessage() . "''"); 182 | \Yii::$app->end(1); 183 | } 184 | $this->stdout(' [OK]' . PHP_EOL); 185 | 186 | } 187 | 188 | /** 189 | * Create schema 190 | * 191 | * Note: Loads parameters from ENV vars, if empty. 192 | * 193 | * Creates database and grants permissions to user 194 | * 195 | * @param $root eg. ENV `DB_ENV_MYSQL_ROOT_USER 196 | * @param $rootPassword eg. ENV `DB_ENV_MYSQL_ROOT_USER` 197 | * 198 | * @throws \yii\base\ExitException 199 | */ 200 | public function actionCreate( 201 | $root, 202 | $rootPassword 203 | ) { 204 | $db = \Yii::$app->get($this->db); 205 | $opts = CliHelper::getMysqlOptsFromDsn($db); 206 | 207 | $dbName = $opts['db']; 208 | $dsn = 'mysql:host=' . $opts['host'] . ';port=' . $opts['port']; 209 | $user = $db->username; 210 | $password = $db->password; 211 | 212 | if (empty($password)) { 213 | $this->stderr('Configuration failed, aborting.'); 214 | return; 215 | } 216 | 217 | $cmd = "CREATE DATABASE IF NOT EXISTS `{$dbName}`; 218 | CREATE USER IF NOT EXISTS '{$user}'@'%' IDENTIFIED BY '{$password}'; 219 | GRANT ALL ON `{$dbName}`.* TO '{$user}'@'%'; 220 | FLUSH PRIVILEGES;"; 221 | if (!$this->dryRun) { 222 | // wait for database connection (BC) 223 | $this->actionWaitForConnection($root, $rootPassword); 224 | 225 | // try to create a database for the user 226 | $this->stdout( 227 | "Creating database from DSN for '{$user}' with user '{$root}'" 228 | ); 229 | 230 | $pdo = new \PDO($dsn, $root, $rootPassword); 231 | $pdo->exec($cmd); 232 | 233 | $this->stdout(' [OK]'); 234 | $this->stdout("\n"); 235 | } else { 236 | $this->stdout($cmd); 237 | } 238 | } 239 | 240 | /** 241 | * Remove schema 242 | * 243 | * @param $root eg. ENV `DB_ENV_MYSQL_ROOT_USER 244 | * @param $rootPassword eg. ENV `DB_ENV_MYSQL_ROOT_USER` 245 | */ 246 | public function actionDestroy( 247 | $root, 248 | $rootPassword 249 | ) { 250 | if ($this->confirm('This is a destructive operation! Continue?', !$this->interactive)) { 251 | $db = \Yii::$app->get($this->db); 252 | $opts = CliHelper::getMysqlOptsFromDsn($db); 253 | 254 | $dbName = $opts['db']; 255 | $dsn = $db->dsn; 256 | $user = $db->username; 257 | 258 | $pdo = new \PDO($dsn, $root, $rootPassword); 259 | 260 | $this->stdout('Deleting database...' . PHP_EOL); 261 | $pdo->exec("DROP DATABASE `{$dbName}`"); 262 | $this->stdout("Deleting user '{$user}'..." . PHP_EOL); 263 | $pdo->exec("DROP USER '{$user}'@'%'"); 264 | $pdo->exec('FLUSH PRIVILEGES'); 265 | } 266 | } 267 | 268 | 269 | /** 270 | * Export tables (INSERT only) 271 | * @throws \yii\base\Exception 272 | * @since 0.8.0 273 | */ 274 | public function actionExport() 275 | { 276 | $latestMigrationId = $this->getLatestMigrationId(); 277 | $date = date('ymd_His'); 278 | $fileName = "{$latestMigrationId}x_export_at_{$date}.sql"; 279 | 280 | $db = \Yii::$app->get($this->db); 281 | $opts = CliHelper::getMysqlOptsFromDsn($db); 282 | 283 | $command = CliHelper::getMysqlCommand('mysqldump', $db); 284 | $command->addArg('--no-create-info'); 285 | $command->addArg('--skip-extended-insert'); 286 | $command->addArg('--quick'); 287 | $command->addArg('--no-autocommit'); 288 | $command->addArg('--disable-keys'); 289 | 290 | // exclude-tables 291 | if ($this->excludeTables) { 292 | foreach ($this->excludeTables as $excludedTable) { 293 | $command->addArg('--ignore-table', $opts['db'] . '.' . $excludedTable); 294 | } 295 | } 296 | 297 | // database 298 | $command->addArg($opts['db']); 299 | 300 | // include tables 301 | if ($this->includeTables) { 302 | foreach ($this->includeTables as $includedTable) { 303 | $command->addArg($includedTable); 304 | } 305 | } 306 | 307 | if (!$this->dryRun) { 308 | $command->execute(); 309 | } else { 310 | $this->stdout($command->getExecCommand()); 311 | return; 312 | } 313 | 314 | if ($command->getError()) { 315 | $this->stderr($command->getError() . "\n"); 316 | \Yii::$app->end(1); 317 | } 318 | 319 | $dir = \Yii::getAlias($this->outputPath); 320 | FileHelper::createDirectory($dir); 321 | 322 | $dump = $command->getOutput(); 323 | if ($this->truncateTables) { 324 | $dump = preg_replace('/LOCK TABLES (.+) WRITE;/', 'LOCK TABLES $1 WRITE; TRUNCATE TABLE $1;', $dump); 325 | } 326 | 327 | $file = \Yii::getAlias($dir . '/' . $fileName); 328 | file_put_contents($file, $dump); 329 | 330 | $this->stdout("MySQL export successfully written to '$file'", Console::FG_GREEN); 331 | } 332 | 333 | 334 | /** 335 | * Dump schema (all tables) 336 | * 337 | * @throws Exception 338 | */ 339 | public function actionDump() 340 | { 341 | // prepare vars 342 | $date = date('ymd_His'); 343 | $dir = $this->outputPath; 344 | $appName = \Yii::$app->id; 345 | $file = \Yii::getAlias($dir . "/d{$date}_{$appName}.sql"); 346 | $db = \Yii::$app->get($this->db); 347 | $opts = CliHelper::getMysqlOptsFromDsn($db); 348 | 349 | FileHelper::createDirectory($dir); 350 | 351 | // dump tables with data 352 | $command = CliHelper::getMysqlCommand('mysqldump', $db); 353 | $command->addArg('--no-tablespaces'); 354 | $command->addArg('--opt'); 355 | 356 | if ($this->noDataTables) { 357 | $noDataTables = explode(',', $this->noDataTables); 358 | 359 | foreach ($noDataTables as $table) { 360 | $command->addArg('--ignore-table', $opts['db'] . '.' . $table); 361 | } 362 | } 363 | $command->addArg($opts['db']); 364 | $command->addArg(' > ', '', false); 365 | $command->addArg($file); 366 | if ($this->dryRun) { 367 | $this->stdout($command->getExecCommand() . PHP_EOL); 368 | } else { 369 | if ($this->verbose) { 370 | $this->stdout("Dumping tables with data..."); 371 | } 372 | $this->execute($command); 373 | } 374 | 375 | 376 | if ($this->noDataTables) { 377 | // dump tables without data 378 | $commandNoData = CliHelper::getMysqlCommand('mysqldump', $db); 379 | $commandNoData->addArg('--no-tablespaces'); 380 | $commandNoData->addArg('--no-data'); 381 | $commandNoData->addArg('--opt'); 382 | $commandNoData->addArg($opts['db']); 383 | 384 | foreach ($noDataTables as $table) { 385 | $commandNoData->addArg($table); 386 | } 387 | $commandNoData->addArg('>>', '', false); 388 | $commandNoData->addArg($file); 389 | if ($this->dryRun) { 390 | $this->stdout($commandNoData->getExecCommand()); 391 | } else { 392 | if ($this->verbose) { 393 | $this->stdout("no data tables..."); 394 | } 395 | $this->execute($commandNoData); 396 | } 397 | } 398 | 399 | if ($this->verbose) { 400 | $this->stdout("done." . PHP_EOL); 401 | } 402 | $this->stdout($file); 403 | } 404 | 405 | /** 406 | * Import from file to database and flush cache 407 | * @param $file 408 | * @throws \yii\base\InvalidConfigException 409 | */ 410 | public function actionImport($file) 411 | { 412 | $db = \Yii::$app->get($this->db); 413 | $opts = CliHelper::getMysqlOptsFromDsn($db); 414 | $command = CliHelper::getMysqlCommand('mysql', $db); 415 | $command->addArg('-D', $opts['db']); 416 | $command->addArg('<', null, false); 417 | $command->addArg($file); 418 | 419 | if ($this->dryRun) { 420 | $this->stdout($command->getExecCommand()); 421 | } else { 422 | if ($this->confirm('This is a destructive operation! Continue?', !$this->interactive)) { 423 | if (!$command->execute()) { 424 | $this->stderr($command->getError()); 425 | $this->stderr(PHP_EOL); 426 | } 427 | } 428 | 429 | \Yii::$app->cache->flush(); 430 | } 431 | } 432 | 433 | /** 434 | * @param $cmd 435 | * 436 | * @return mixed 437 | * @throws Exception 438 | */ 439 | private function execute($cmd) 440 | { 441 | $command = new Command(); 442 | $command->setCommand($cmd); 443 | if ($command->execute()) { 444 | return $command->getOutput(); 445 | } else { 446 | throw new Exception($command->getError()); 447 | } 448 | } 449 | 450 | private function getFilePrefix() 451 | { 452 | $sanitizedVersion = defined('APP_VERSION') ? 453 | '_' . Inflector::slug(Inflector::camel2words(trim(APP_VERSION, '_')), '_') : 454 | ''; 455 | return 'm' . gmdate('ymd_His') . '_' . \Yii::$app->id . $sanitizedVersion; 456 | } 457 | 458 | /** 459 | * @return mixed return the last applied migration id (m123456_123456) 460 | */ 461 | private function getLatestMigrationId(){ 462 | $command = new Command(); 463 | $command->setCommand('yii migrate/history 1'); 464 | $command->execute(); 465 | $output = $command->getOutput(); 466 | preg_match('/m[0-9_]{6}_[0-9_]{6}/', $output, $matches); 467 | $latestMigrationId = $matches[0]; 468 | return $latestMigrationId; 469 | } 470 | } 471 | -------------------------------------------------------------------------------- /tests/_support/_generated/AcceptanceTesterActions.php: -------------------------------------------------------------------------------- 1 | getScenario()->runStep(new \Codeception\Step\Action('debugWebDriverLogs', func_get_args())); 27 | } 28 | 29 | 30 | /** 31 | * [!] Method is generated. Documentation taken from corresponding module. 32 | * 33 | * Changes the subdomain for the 'url' configuration parameter. 34 | * Does not open a page; use `amOnPage` for that. 35 | * 36 | * ``` php 37 | * amOnSubdomain('user'); 43 | * $I->amOnPage('/'); 44 | * // moves to http://user.mysite.com/ 45 | * ?> 46 | * ``` 47 | * 48 | * @param $subdomain 49 | * 50 | * @return mixed 51 | * @see \Codeception\Module\WebDriver::amOnSubdomain() 52 | */ 53 | public function amOnSubdomain($subdomain) { 54 | return $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnSubdomain', func_get_args())); 55 | } 56 | 57 | 58 | /** 59 | * [!] Method is generated. Documentation taken from corresponding module. 60 | * 61 | * Takes a screenshot of the current window and saves it to `tests/_output/debug`. 62 | * 63 | * ``` php 64 | * amOnPage('/user/edit'); 66 | * $I->makeScreenshot('edit_page'); 67 | * // saved to: tests/_output/debug/edit_page.png 68 | * ?> 69 | * ``` 70 | * 71 | * @param $name 72 | * @see \Codeception\Module\WebDriver::makeScreenshot() 73 | */ 74 | public function makeScreenshot($name) { 75 | return $this->getScenario()->runStep(new \Codeception\Step\Action('makeScreenshot', func_get_args())); 76 | } 77 | 78 | 79 | /** 80 | * [!] Method is generated. Documentation taken from corresponding module. 81 | * 82 | * Resize the current window. 83 | * 84 | * ``` php 85 | * resizeWindow(800, 600); 87 | * 88 | * ``` 89 | * 90 | * @param int $width 91 | * @param int $height 92 | * @see \Codeception\Module\WebDriver::resizeWindow() 93 | */ 94 | public function resizeWindow($width, $height) { 95 | return $this->getScenario()->runStep(new \Codeception\Step\Action('resizeWindow', func_get_args())); 96 | } 97 | 98 | 99 | /** 100 | * [!] Method is generated. Documentation taken from corresponding module. 101 | * 102 | * Checks that a cookie with the given name is set. 103 | * You can set additional cookie params like `domain`, `path` as array passed in last argument. 104 | * 105 | * ``` php 106 | * seeCookie('PHPSESSID'); 108 | * ?> 109 | * ``` 110 | * 111 | * @param $cookie 112 | * @param array $params 113 | * @return mixed 114 | * Conditional Assertion: Test won't be stopped on fail 115 | * @see \Codeception\Module\WebDriver::seeCookie() 116 | */ 117 | public function canSeeCookie($cookie, $params = null) { 118 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCookie', func_get_args())); 119 | } 120 | /** 121 | * [!] Method is generated. Documentation taken from corresponding module. 122 | * 123 | * Checks that a cookie with the given name is set. 124 | * You can set additional cookie params like `domain`, `path` as array passed in last argument. 125 | * 126 | * ``` php 127 | * seeCookie('PHPSESSID'); 129 | * ?> 130 | * ``` 131 | * 132 | * @param $cookie 133 | * @param array $params 134 | * @return mixed 135 | * @see \Codeception\Module\WebDriver::seeCookie() 136 | */ 137 | public function seeCookie($cookie, $params = null) { 138 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCookie', func_get_args())); 139 | } 140 | 141 | 142 | /** 143 | * [!] Method is generated. Documentation taken from corresponding module. 144 | * 145 | * Checks that there isn't a cookie with the given name. 146 | * You can set additional cookie params like `domain`, `path` as array passed in last argument. 147 | * 148 | * @param $cookie 149 | * 150 | * @param array $params 151 | * @return mixed 152 | * Conditional Assertion: Test won't be stopped on fail 153 | * @see \Codeception\Module\WebDriver::dontSeeCookie() 154 | */ 155 | public function cantSeeCookie($cookie, $params = null) { 156 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCookie', func_get_args())); 157 | } 158 | /** 159 | * [!] Method is generated. Documentation taken from corresponding module. 160 | * 161 | * Checks that there isn't a cookie with the given name. 162 | * You can set additional cookie params like `domain`, `path` as array passed in last argument. 163 | * 164 | * @param $cookie 165 | * 166 | * @param array $params 167 | * @return mixed 168 | * @see \Codeception\Module\WebDriver::dontSeeCookie() 169 | */ 170 | public function dontSeeCookie($cookie, $params = null) { 171 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeCookie', func_get_args())); 172 | } 173 | 174 | 175 | /** 176 | * [!] Method is generated. Documentation taken from corresponding module. 177 | * 178 | * Sets a cookie with the given name and value. 179 | * You can set additional cookie params like `domain`, `path`, `expires`, `secure` in array passed as last argument. 180 | * 181 | * ``` php 182 | * setCookie('PHPSESSID', 'el4ukv0kqbvoirg7nkp4dncpk3'); 184 | * ?> 185 | * ``` 186 | * 187 | * @param $name 188 | * @param $val 189 | * @param array $params 190 | * 191 | * @return mixed 192 | * @see \Codeception\Module\WebDriver::setCookie() 193 | */ 194 | public function setCookie($cookie, $value, $params = null) { 195 | return $this->getScenario()->runStep(new \Codeception\Step\Action('setCookie', func_get_args())); 196 | } 197 | 198 | 199 | /** 200 | * [!] Method is generated. Documentation taken from corresponding module. 201 | * 202 | * Unsets cookie with the given name. 203 | * You can set additional cookie params like `domain`, `path` in array passed as last argument. 204 | * 205 | * @param $cookie 206 | * 207 | * @param array $params 208 | * @return mixed 209 | * @see \Codeception\Module\WebDriver::resetCookie() 210 | */ 211 | public function resetCookie($cookie, $params = null) { 212 | return $this->getScenario()->runStep(new \Codeception\Step\Action('resetCookie', func_get_args())); 213 | } 214 | 215 | 216 | /** 217 | * [!] Method is generated. Documentation taken from corresponding module. 218 | * 219 | * Grabs a cookie value. 220 | * You can set additional cookie params like `domain`, `path` in array passed as last argument. 221 | * 222 | * @param $cookie 223 | * 224 | * @param array $params 225 | * @return mixed 226 | * @see \Codeception\Module\WebDriver::grabCookie() 227 | */ 228 | public function grabCookie($cookie, $params = null) { 229 | return $this->getScenario()->runStep(new \Codeception\Step\Action('grabCookie', func_get_args())); 230 | } 231 | 232 | 233 | /** 234 | * [!] Method is generated. Documentation taken from corresponding module. 235 | * 236 | * Open web page at the given absolute URL and sets its hostname as the base host. 237 | * 238 | * ``` php 239 | * amOnUrl('http://codeception.com'); 241 | * $I->amOnPage('/quickstart'); // moves to http://codeception.com/quickstart 242 | * ?> 243 | * ``` 244 | * @see \Codeception\Module\WebDriver::amOnUrl() 245 | */ 246 | public function amOnUrl($url) { 247 | return $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnUrl', func_get_args())); 248 | } 249 | 250 | 251 | /** 252 | * [!] Method is generated. Documentation taken from corresponding module. 253 | * 254 | * Opens the page for the given relative URI. 255 | * 256 | * ``` php 257 | * amOnPage('/'); 260 | * // opens /register page 261 | * $I->amOnPage('/register'); 262 | * ``` 263 | * 264 | * @param $page 265 | * @see \Codeception\Module\WebDriver::amOnPage() 266 | */ 267 | public function amOnPage($page) { 268 | return $this->getScenario()->runStep(new \Codeception\Step\Condition('amOnPage', func_get_args())); 269 | } 270 | 271 | 272 | /** 273 | * [!] Method is generated. Documentation taken from corresponding module. 274 | * 275 | * Checks that the current page contains the given string (case insensitive). 276 | * 277 | * You can specify a specific HTML element (via CSS or XPath) as the second 278 | * parameter to only search within that element. 279 | * 280 | * ``` php 281 | * see('Logout'); // I can suppose user is logged in 283 | * $I->see('Sign Up', 'h1'); // I can suppose it's a signup page 284 | * $I->see('Sign Up', '//body/h1'); // with XPath 285 | * ``` 286 | * 287 | * Note that the search is done after stripping all HTML tags from the body, 288 | * so `$I->see('strong')` will return true for strings like: 289 | * 290 | * - `

I am Stronger than thou

` 291 | * - `` 292 | * 293 | * But will *not* be true for strings like: 294 | * 295 | * - `Home` 296 | * - `
Home` 297 | * - `` 298 | * 299 | * For checking the raw source code, use `seeInSource()`. 300 | * 301 | * @param $text 302 | * @param null $selector 303 | * Conditional Assertion: Test won't be stopped on fail 304 | * @see \Codeception\Module\WebDriver::see() 305 | */ 306 | public function canSee($text, $selector = null) { 307 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('see', func_get_args())); 308 | } 309 | /** 310 | * [!] Method is generated. Documentation taken from corresponding module. 311 | * 312 | * Checks that the current page contains the given string (case insensitive). 313 | * 314 | * You can specify a specific HTML element (via CSS or XPath) as the second 315 | * parameter to only search within that element. 316 | * 317 | * ``` php 318 | * see('Logout'); // I can suppose user is logged in 320 | * $I->see('Sign Up', 'h1'); // I can suppose it's a signup page 321 | * $I->see('Sign Up', '//body/h1'); // with XPath 322 | * ``` 323 | * 324 | * Note that the search is done after stripping all HTML tags from the body, 325 | * so `$I->see('strong')` will return true for strings like: 326 | * 327 | * - `

I am Stronger than thou

` 328 | * - `` 329 | * 330 | * But will *not* be true for strings like: 331 | * 332 | * - `Home` 333 | * - `
Home` 334 | * - `` 335 | * 336 | * For checking the raw source code, use `seeInSource()`. 337 | * 338 | * @param $text 339 | * @param null $selector 340 | * @see \Codeception\Module\WebDriver::see() 341 | */ 342 | public function see($text, $selector = null) { 343 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('see', func_get_args())); 344 | } 345 | 346 | 347 | /** 348 | * [!] Method is generated. Documentation taken from corresponding module. 349 | * 350 | * Checks that the current page doesn't contain the text specified (case insensitive). 351 | * Give a locator as the second parameter to match a specific region. 352 | * 353 | * ```php 354 | * dontSee('Login'); // I can suppose user is already logged in 356 | * $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page 357 | * $I->dontSee('Sign Up','//body/h1'); // with XPath 358 | * ``` 359 | * 360 | * Note that the search is done after stripping all HTML tags from the body, 361 | * so `$I->dontSee('strong')` will fail on strings like: 362 | * 363 | * - `

I am Stronger than thou

` 364 | * - `` 365 | * 366 | * But will ignore strings like: 367 | * 368 | * - `Home` 369 | * - `
Home` 370 | * - `` 371 | * 372 | * For checking the raw source code, use `seeInSource()`. 373 | * 374 | * @param $text 375 | * @param null $selector 376 | * Conditional Assertion: Test won't be stopped on fail 377 | * @see \Codeception\Module\WebDriver::dontSee() 378 | */ 379 | public function cantSee($text, $selector = null) { 380 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSee', func_get_args())); 381 | } 382 | /** 383 | * [!] Method is generated. Documentation taken from corresponding module. 384 | * 385 | * Checks that the current page doesn't contain the text specified (case insensitive). 386 | * Give a locator as the second parameter to match a specific region. 387 | * 388 | * ```php 389 | * dontSee('Login'); // I can suppose user is already logged in 391 | * $I->dontSee('Sign Up','h1'); // I can suppose it's not a signup page 392 | * $I->dontSee('Sign Up','//body/h1'); // with XPath 393 | * ``` 394 | * 395 | * Note that the search is done after stripping all HTML tags from the body, 396 | * so `$I->dontSee('strong')` will fail on strings like: 397 | * 398 | * - `

I am Stronger than thou

` 399 | * - `` 400 | * 401 | * But will ignore strings like: 402 | * 403 | * - `Home` 404 | * - `
Home` 405 | * - `` 406 | * 407 | * For checking the raw source code, use `seeInSource()`. 408 | * 409 | * @param $text 410 | * @param null $selector 411 | * @see \Codeception\Module\WebDriver::dontSee() 412 | */ 413 | public function dontSee($text, $selector = null) { 414 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSee', func_get_args())); 415 | } 416 | 417 | 418 | /** 419 | * [!] Method is generated. Documentation taken from corresponding module. 420 | * 421 | * Checks that the current page contains the given string in its 422 | * raw source code. 423 | * 424 | * ``` php 425 | * seeInSource('

Green eggs & ham

'); 427 | * ``` 428 | * 429 | * @param $raw 430 | * Conditional Assertion: Test won't be stopped on fail 431 | * @see \Codeception\Module\WebDriver::seeInSource() 432 | */ 433 | public function canSeeInSource($raw) { 434 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInSource', func_get_args())); 435 | } 436 | /** 437 | * [!] Method is generated. Documentation taken from corresponding module. 438 | * 439 | * Checks that the current page contains the given string in its 440 | * raw source code. 441 | * 442 | * ``` php 443 | * seeInSource('

Green eggs & ham

'); 445 | * ``` 446 | * 447 | * @param $raw 448 | * @see \Codeception\Module\WebDriver::seeInSource() 449 | */ 450 | public function seeInSource($raw) { 451 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInSource', func_get_args())); 452 | } 453 | 454 | 455 | /** 456 | * [!] Method is generated. Documentation taken from corresponding module. 457 | * 458 | * Checks that the current page contains the given string in its 459 | * raw source code. 460 | * 461 | * ```php 462 | * dontSeeInSource('

Green eggs & ham

'); 464 | * ``` 465 | * 466 | * @param $raw 467 | * Conditional Assertion: Test won't be stopped on fail 468 | * @see \Codeception\Module\WebDriver::dontSeeInSource() 469 | */ 470 | public function cantSeeInSource($raw) { 471 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInSource', func_get_args())); 472 | } 473 | /** 474 | * [!] Method is generated. Documentation taken from corresponding module. 475 | * 476 | * Checks that the current page contains the given string in its 477 | * raw source code. 478 | * 479 | * ```php 480 | * dontSeeInSource('

Green eggs & ham

'); 482 | * ``` 483 | * 484 | * @param $raw 485 | * @see \Codeception\Module\WebDriver::dontSeeInSource() 486 | */ 487 | public function dontSeeInSource($raw) { 488 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInSource', func_get_args())); 489 | } 490 | 491 | 492 | /** 493 | * [!] Method is generated. Documentation taken from corresponding module. 494 | * 495 | * Checks that the page source contains the given string. 496 | * 497 | * ```php 498 | * seeInPageSource('getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInPageSource', func_get_args())); 508 | } 509 | /** 510 | * [!] Method is generated. Documentation taken from corresponding module. 511 | * 512 | * Checks that the page source contains the given string. 513 | * 514 | * ```php 515 | * seeInPageSource('getScenario()->runStep(new \Codeception\Step\Assertion('seeInPageSource', func_get_args())); 524 | } 525 | 526 | 527 | /** 528 | * [!] Method is generated. Documentation taken from corresponding module. 529 | * 530 | * Checks that the page source doesn't contain the given string. 531 | * 532 | * @param $text 533 | * Conditional Assertion: Test won't be stopped on fail 534 | * @see \Codeception\Module\WebDriver::dontSeeInPageSource() 535 | */ 536 | public function cantSeeInPageSource($text) { 537 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInPageSource', func_get_args())); 538 | } 539 | /** 540 | * [!] Method is generated. Documentation taken from corresponding module. 541 | * 542 | * Checks that the page source doesn't contain the given string. 543 | * 544 | * @param $text 545 | * @see \Codeception\Module\WebDriver::dontSeeInPageSource() 546 | */ 547 | public function dontSeeInPageSource($text) { 548 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInPageSource', func_get_args())); 549 | } 550 | 551 | 552 | /** 553 | * [!] Method is generated. Documentation taken from corresponding module. 554 | * 555 | * Perform a click on a link or a button, given by a locator. 556 | * If a fuzzy locator is given, the page will be searched for a button, link, or image matching the locator string. 557 | * For buttons, the "value" attribute, "name" attribute, and inner text are searched. 558 | * For links, the link text is searched. 559 | * For images, the "alt" attribute and inner text of any parent links are searched. 560 | * 561 | * The second parameter is a context (CSS or XPath locator) to narrow the search. 562 | * 563 | * Note that if the locator matches a button of type `submit`, the form will be submitted. 564 | * 565 | * ``` php 566 | * click('Logout'); 569 | * // button of form 570 | * $I->click('Submit'); 571 | * // CSS button 572 | * $I->click('#form input[type=submit]'); 573 | * // XPath 574 | * $I->click('//form/*[@type=submit]'); 575 | * // link in context 576 | * $I->click('Logout', '#nav'); 577 | * // using strict locator 578 | * $I->click(['link' => 'Login']); 579 | * ?> 580 | * ``` 581 | * 582 | * @param $link 583 | * @param $context 584 | * @see \Codeception\Module\WebDriver::click() 585 | */ 586 | public function click($link, $context = null) { 587 | return $this->getScenario()->runStep(new \Codeception\Step\Action('click', func_get_args())); 588 | } 589 | 590 | 591 | /** 592 | * [!] Method is generated. Documentation taken from corresponding module. 593 | * 594 | * Checks that there's a link with the specified text. 595 | * Give a full URL as the second parameter to match links with that exact URL. 596 | * 597 | * ``` php 598 | * seeLink('Logout'); // matches Logout 600 | * $I->seeLink('Logout','/logout'); // matches Logout 601 | * ?> 602 | * ``` 603 | * 604 | * @param $text 605 | * @param null $url 606 | * Conditional Assertion: Test won't be stopped on fail 607 | * @see \Codeception\Module\WebDriver::seeLink() 608 | */ 609 | public function canSeeLink($text, $url = null) { 610 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeLink', func_get_args())); 611 | } 612 | /** 613 | * [!] Method is generated. Documentation taken from corresponding module. 614 | * 615 | * Checks that there's a link with the specified text. 616 | * Give a full URL as the second parameter to match links with that exact URL. 617 | * 618 | * ``` php 619 | * seeLink('Logout'); // matches Logout 621 | * $I->seeLink('Logout','/logout'); // matches Logout 622 | * ?> 623 | * ``` 624 | * 625 | * @param $text 626 | * @param null $url 627 | * @see \Codeception\Module\WebDriver::seeLink() 628 | */ 629 | public function seeLink($text, $url = null) { 630 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeLink', func_get_args())); 631 | } 632 | 633 | 634 | /** 635 | * [!] Method is generated. Documentation taken from corresponding module. 636 | * 637 | * Checks that the page doesn't contain a link with the given string. 638 | * If the second parameter is given, only links with a matching "href" attribute will be checked. 639 | * 640 | * ``` php 641 | * dontSeeLink('Logout'); // I suppose user is not logged in 643 | * $I->dontSeeLink('Checkout now', '/store/cart.php'); 644 | * ?> 645 | * ``` 646 | * 647 | * @param $text 648 | * @param null $url 649 | * Conditional Assertion: Test won't be stopped on fail 650 | * @see \Codeception\Module\WebDriver::dontSeeLink() 651 | */ 652 | public function cantSeeLink($text, $url = null) { 653 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeLink', func_get_args())); 654 | } 655 | /** 656 | * [!] Method is generated. Documentation taken from corresponding module. 657 | * 658 | * Checks that the page doesn't contain a link with the given string. 659 | * If the second parameter is given, only links with a matching "href" attribute will be checked. 660 | * 661 | * ``` php 662 | * dontSeeLink('Logout'); // I suppose user is not logged in 664 | * $I->dontSeeLink('Checkout now', '/store/cart.php'); 665 | * ?> 666 | * ``` 667 | * 668 | * @param $text 669 | * @param null $url 670 | * @see \Codeception\Module\WebDriver::dontSeeLink() 671 | */ 672 | public function dontSeeLink($text, $url = null) { 673 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeLink', func_get_args())); 674 | } 675 | 676 | 677 | /** 678 | * [!] Method is generated. Documentation taken from corresponding module. 679 | * 680 | * Checks that current URI contains the given string. 681 | * 682 | * ``` php 683 | * seeInCurrentUrl('home'); 686 | * // to match: /users/1 687 | * $I->seeInCurrentUrl('/users/'); 688 | * ?> 689 | * ``` 690 | * 691 | * @param $uri 692 | * Conditional Assertion: Test won't be stopped on fail 693 | * @see \Codeception\Module\WebDriver::seeInCurrentUrl() 694 | */ 695 | public function canSeeInCurrentUrl($uri) { 696 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInCurrentUrl', func_get_args())); 697 | } 698 | /** 699 | * [!] Method is generated. Documentation taken from corresponding module. 700 | * 701 | * Checks that current URI contains the given string. 702 | * 703 | * ``` php 704 | * seeInCurrentUrl('home'); 707 | * // to match: /users/1 708 | * $I->seeInCurrentUrl('/users/'); 709 | * ?> 710 | * ``` 711 | * 712 | * @param $uri 713 | * @see \Codeception\Module\WebDriver::seeInCurrentUrl() 714 | */ 715 | public function seeInCurrentUrl($uri) { 716 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInCurrentUrl', func_get_args())); 717 | } 718 | 719 | 720 | /** 721 | * [!] Method is generated. Documentation taken from corresponding module. 722 | * 723 | * Checks that the current URL is equal to the given string. 724 | * Unlike `seeInCurrentUrl`, this only matches the full URL. 725 | * 726 | * ``` php 727 | * seeCurrentUrlEquals('/'); 730 | * ?> 731 | * ``` 732 | * 733 | * @param $uri 734 | * Conditional Assertion: Test won't be stopped on fail 735 | * @see \Codeception\Module\WebDriver::seeCurrentUrlEquals() 736 | */ 737 | public function canSeeCurrentUrlEquals($uri) { 738 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCurrentUrlEquals', func_get_args())); 739 | } 740 | /** 741 | * [!] Method is generated. Documentation taken from corresponding module. 742 | * 743 | * Checks that the current URL is equal to the given string. 744 | * Unlike `seeInCurrentUrl`, this only matches the full URL. 745 | * 746 | * ``` php 747 | * seeCurrentUrlEquals('/'); 750 | * ?> 751 | * ``` 752 | * 753 | * @param $uri 754 | * @see \Codeception\Module\WebDriver::seeCurrentUrlEquals() 755 | */ 756 | public function seeCurrentUrlEquals($uri) { 757 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCurrentUrlEquals', func_get_args())); 758 | } 759 | 760 | 761 | /** 762 | * [!] Method is generated. Documentation taken from corresponding module. 763 | * 764 | * Checks that the current URL matches the given regular expression. 765 | * 766 | * ``` php 767 | * seeCurrentUrlMatches('~$/users/(\d+)~'); 770 | * ?> 771 | * ``` 772 | * 773 | * @param $uri 774 | * Conditional Assertion: Test won't be stopped on fail 775 | * @see \Codeception\Module\WebDriver::seeCurrentUrlMatches() 776 | */ 777 | public function canSeeCurrentUrlMatches($uri) { 778 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCurrentUrlMatches', func_get_args())); 779 | } 780 | /** 781 | * [!] Method is generated. Documentation taken from corresponding module. 782 | * 783 | * Checks that the current URL matches the given regular expression. 784 | * 785 | * ``` php 786 | * seeCurrentUrlMatches('~$/users/(\d+)~'); 789 | * ?> 790 | * ``` 791 | * 792 | * @param $uri 793 | * @see \Codeception\Module\WebDriver::seeCurrentUrlMatches() 794 | */ 795 | public function seeCurrentUrlMatches($uri) { 796 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCurrentUrlMatches', func_get_args())); 797 | } 798 | 799 | 800 | /** 801 | * [!] Method is generated. Documentation taken from corresponding module. 802 | * 803 | * Checks that the current URI doesn't contain the given string. 804 | * 805 | * ``` php 806 | * dontSeeInCurrentUrl('/users/'); 808 | * ?> 809 | * ``` 810 | * 811 | * @param $uri 812 | * Conditional Assertion: Test won't be stopped on fail 813 | * @see \Codeception\Module\WebDriver::dontSeeInCurrentUrl() 814 | */ 815 | public function cantSeeInCurrentUrl($uri) { 816 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInCurrentUrl', func_get_args())); 817 | } 818 | /** 819 | * [!] Method is generated. Documentation taken from corresponding module. 820 | * 821 | * Checks that the current URI doesn't contain the given string. 822 | * 823 | * ``` php 824 | * dontSeeInCurrentUrl('/users/'); 826 | * ?> 827 | * ``` 828 | * 829 | * @param $uri 830 | * @see \Codeception\Module\WebDriver::dontSeeInCurrentUrl() 831 | */ 832 | public function dontSeeInCurrentUrl($uri) { 833 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInCurrentUrl', func_get_args())); 834 | } 835 | 836 | 837 | /** 838 | * [!] Method is generated. Documentation taken from corresponding module. 839 | * 840 | * Checks that the current URL doesn't equal the given string. 841 | * Unlike `dontSeeInCurrentUrl`, this only matches the full URL. 842 | * 843 | * ``` php 844 | * dontSeeCurrentUrlEquals('/'); 847 | * ?> 848 | * ``` 849 | * 850 | * @param $uri 851 | * Conditional Assertion: Test won't be stopped on fail 852 | * @see \Codeception\Module\WebDriver::dontSeeCurrentUrlEquals() 853 | */ 854 | public function cantSeeCurrentUrlEquals($uri) { 855 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCurrentUrlEquals', func_get_args())); 856 | } 857 | /** 858 | * [!] Method is generated. Documentation taken from corresponding module. 859 | * 860 | * Checks that the current URL doesn't equal the given string. 861 | * Unlike `dontSeeInCurrentUrl`, this only matches the full URL. 862 | * 863 | * ``` php 864 | * dontSeeCurrentUrlEquals('/'); 867 | * ?> 868 | * ``` 869 | * 870 | * @param $uri 871 | * @see \Codeception\Module\WebDriver::dontSeeCurrentUrlEquals() 872 | */ 873 | public function dontSeeCurrentUrlEquals($uri) { 874 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeCurrentUrlEquals', func_get_args())); 875 | } 876 | 877 | 878 | /** 879 | * [!] Method is generated. Documentation taken from corresponding module. 880 | * 881 | * Checks that current url doesn't match the given regular expression. 882 | * 883 | * ``` php 884 | * dontSeeCurrentUrlMatches('~$/users/(\d+)~'); 887 | * ?> 888 | * ``` 889 | * 890 | * @param $uri 891 | * Conditional Assertion: Test won't be stopped on fail 892 | * @see \Codeception\Module\WebDriver::dontSeeCurrentUrlMatches() 893 | */ 894 | public function cantSeeCurrentUrlMatches($uri) { 895 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCurrentUrlMatches', func_get_args())); 896 | } 897 | /** 898 | * [!] Method is generated. Documentation taken from corresponding module. 899 | * 900 | * Checks that current url doesn't match the given regular expression. 901 | * 902 | * ``` php 903 | * dontSeeCurrentUrlMatches('~$/users/(\d+)~'); 906 | * ?> 907 | * ``` 908 | * 909 | * @param $uri 910 | * @see \Codeception\Module\WebDriver::dontSeeCurrentUrlMatches() 911 | */ 912 | public function dontSeeCurrentUrlMatches($uri) { 913 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeCurrentUrlMatches', func_get_args())); 914 | } 915 | 916 | 917 | /** 918 | * [!] Method is generated. Documentation taken from corresponding module. 919 | * 920 | * Executes the given regular expression against the current URI and returns the first match. 921 | * If no parameters are provided, the full URI is returned. 922 | * 923 | * ``` php 924 | * grabFromCurrentUrl('~$/user/(\d+)/~'); 926 | * $uri = $I->grabFromCurrentUrl(); 927 | * ?> 928 | * ``` 929 | * 930 | * @param null $uri 931 | * 932 | * @return mixed 933 | * @see \Codeception\Module\WebDriver::grabFromCurrentUrl() 934 | */ 935 | public function grabFromCurrentUrl($uri = null) { 936 | return $this->getScenario()->runStep(new \Codeception\Step\Action('grabFromCurrentUrl', func_get_args())); 937 | } 938 | 939 | 940 | /** 941 | * [!] Method is generated. Documentation taken from corresponding module. 942 | * 943 | * Checks that the specified checkbox is checked. 944 | * 945 | * ``` php 946 | * seeCheckboxIsChecked('#agree'); // I suppose user agreed to terms 948 | * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user agreed to terms, If there is only one checkbox in form. 949 | * $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); 950 | * ?> 951 | * ``` 952 | * 953 | * @param $checkbox 954 | * Conditional Assertion: Test won't be stopped on fail 955 | * @see \Codeception\Module\WebDriver::seeCheckboxIsChecked() 956 | */ 957 | public function canSeeCheckboxIsChecked($checkbox) { 958 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeCheckboxIsChecked', func_get_args())); 959 | } 960 | /** 961 | * [!] Method is generated. Documentation taken from corresponding module. 962 | * 963 | * Checks that the specified checkbox is checked. 964 | * 965 | * ``` php 966 | * seeCheckboxIsChecked('#agree'); // I suppose user agreed to terms 968 | * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user agreed to terms, If there is only one checkbox in form. 969 | * $I->seeCheckboxIsChecked('//form/input[@type=checkbox and @name=agree]'); 970 | * ?> 971 | * ``` 972 | * 973 | * @param $checkbox 974 | * @see \Codeception\Module\WebDriver::seeCheckboxIsChecked() 975 | */ 976 | public function seeCheckboxIsChecked($checkbox) { 977 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeCheckboxIsChecked', func_get_args())); 978 | } 979 | 980 | 981 | /** 982 | * [!] Method is generated. Documentation taken from corresponding module. 983 | * 984 | * Check that the specified checkbox is unchecked. 985 | * 986 | * ``` php 987 | * dontSeeCheckboxIsChecked('#agree'); // I suppose user didn't agree to terms 989 | * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user didn't check the first checkbox in form. 990 | * ?> 991 | * ``` 992 | * 993 | * @param $checkbox 994 | * Conditional Assertion: Test won't be stopped on fail 995 | * @see \Codeception\Module\WebDriver::dontSeeCheckboxIsChecked() 996 | */ 997 | public function cantSeeCheckboxIsChecked($checkbox) { 998 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeCheckboxIsChecked', func_get_args())); 999 | } 1000 | /** 1001 | * [!] Method is generated. Documentation taken from corresponding module. 1002 | * 1003 | * Check that the specified checkbox is unchecked. 1004 | * 1005 | * ``` php 1006 | * dontSeeCheckboxIsChecked('#agree'); // I suppose user didn't agree to terms 1008 | * $I->seeCheckboxIsChecked('#signup_form input[type=checkbox]'); // I suppose user didn't check the first checkbox in form. 1009 | * ?> 1010 | * ``` 1011 | * 1012 | * @param $checkbox 1013 | * @see \Codeception\Module\WebDriver::dontSeeCheckboxIsChecked() 1014 | */ 1015 | public function dontSeeCheckboxIsChecked($checkbox) { 1016 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeCheckboxIsChecked', func_get_args())); 1017 | } 1018 | 1019 | 1020 | /** 1021 | * [!] Method is generated. Documentation taken from corresponding module. 1022 | * 1023 | * Checks that the given input field or textarea contains the given value. 1024 | * For fuzzy locators, fields are matched by label text, the "name" attribute, CSS, and XPath. 1025 | * 1026 | * ``` php 1027 | * seeInField('Body','Type your comment here'); 1029 | * $I->seeInField('form textarea[name=body]','Type your comment here'); 1030 | * $I->seeInField('form input[type=hidden]','hidden_value'); 1031 | * $I->seeInField('#searchform input','Search'); 1032 | * $I->seeInField('//form/*[@name=search]','Search'); 1033 | * $I->seeInField(['name' => 'search'], 'Search'); 1034 | * ?> 1035 | * ``` 1036 | * 1037 | * @param $field 1038 | * @param $value 1039 | * Conditional Assertion: Test won't be stopped on fail 1040 | * @see \Codeception\Module\WebDriver::seeInField() 1041 | */ 1042 | public function canSeeInField($field, $value) { 1043 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInField', func_get_args())); 1044 | } 1045 | /** 1046 | * [!] Method is generated. Documentation taken from corresponding module. 1047 | * 1048 | * Checks that the given input field or textarea contains the given value. 1049 | * For fuzzy locators, fields are matched by label text, the "name" attribute, CSS, and XPath. 1050 | * 1051 | * ``` php 1052 | * seeInField('Body','Type your comment here'); 1054 | * $I->seeInField('form textarea[name=body]','Type your comment here'); 1055 | * $I->seeInField('form input[type=hidden]','hidden_value'); 1056 | * $I->seeInField('#searchform input','Search'); 1057 | * $I->seeInField('//form/*[@name=search]','Search'); 1058 | * $I->seeInField(['name' => 'search'], 'Search'); 1059 | * ?> 1060 | * ``` 1061 | * 1062 | * @param $field 1063 | * @param $value 1064 | * @see \Codeception\Module\WebDriver::seeInField() 1065 | */ 1066 | public function seeInField($field, $value) { 1067 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInField', func_get_args())); 1068 | } 1069 | 1070 | 1071 | /** 1072 | * [!] Method is generated. Documentation taken from corresponding module. 1073 | * 1074 | * Checks that an input field or textarea doesn't contain the given value. 1075 | * For fuzzy locators, the field is matched by label text, CSS and XPath. 1076 | * 1077 | * ``` php 1078 | * dontSeeInField('Body','Type your comment here'); 1080 | * $I->dontSeeInField('form textarea[name=body]','Type your comment here'); 1081 | * $I->dontSeeInField('form input[type=hidden]','hidden_value'); 1082 | * $I->dontSeeInField('#searchform input','Search'); 1083 | * $I->dontSeeInField('//form/*[@name=search]','Search'); 1084 | * $I->dontSeeInField(['name' => 'search'], 'Search'); 1085 | * ?> 1086 | * ``` 1087 | * 1088 | * @param $field 1089 | * @param $value 1090 | * Conditional Assertion: Test won't be stopped on fail 1091 | * @see \Codeception\Module\WebDriver::dontSeeInField() 1092 | */ 1093 | public function cantSeeInField($field, $value) { 1094 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInField', func_get_args())); 1095 | } 1096 | /** 1097 | * [!] Method is generated. Documentation taken from corresponding module. 1098 | * 1099 | * Checks that an input field or textarea doesn't contain the given value. 1100 | * For fuzzy locators, the field is matched by label text, CSS and XPath. 1101 | * 1102 | * ``` php 1103 | * dontSeeInField('Body','Type your comment here'); 1105 | * $I->dontSeeInField('form textarea[name=body]','Type your comment here'); 1106 | * $I->dontSeeInField('form input[type=hidden]','hidden_value'); 1107 | * $I->dontSeeInField('#searchform input','Search'); 1108 | * $I->dontSeeInField('//form/*[@name=search]','Search'); 1109 | * $I->dontSeeInField(['name' => 'search'], 'Search'); 1110 | * ?> 1111 | * ``` 1112 | * 1113 | * @param $field 1114 | * @param $value 1115 | * @see \Codeception\Module\WebDriver::dontSeeInField() 1116 | */ 1117 | public function dontSeeInField($field, $value) { 1118 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInField', func_get_args())); 1119 | } 1120 | 1121 | 1122 | /** 1123 | * [!] Method is generated. Documentation taken from corresponding module. 1124 | * 1125 | * Checks if the array of form parameters (name => value) are set on the form matched with the 1126 | * passed selector. 1127 | * 1128 | * ``` php 1129 | * seeInFormFields('form[name=myform]', [ 1131 | * 'input1' => 'value', 1132 | * 'input2' => 'other value', 1133 | * ]); 1134 | * ?> 1135 | * ``` 1136 | * 1137 | * For multi-select elements, or to check values of multiple elements with the same name, an 1138 | * array may be passed: 1139 | * 1140 | * ``` php 1141 | * seeInFormFields('.form-class', [ 1143 | * 'multiselect' => [ 1144 | * 'value1', 1145 | * 'value2', 1146 | * ], 1147 | * 'checkbox[]' => [ 1148 | * 'a checked value', 1149 | * 'another checked value', 1150 | * ], 1151 | * ]); 1152 | * ?> 1153 | * ``` 1154 | * 1155 | * Additionally, checkbox values can be checked with a boolean. 1156 | * 1157 | * ``` php 1158 | * seeInFormFields('#form-id', [ 1160 | * 'checkbox1' => true, // passes if checked 1161 | * 'checkbox2' => false, // passes if unchecked 1162 | * ]); 1163 | * ?> 1164 | * ``` 1165 | * 1166 | * Pair this with submitForm for quick testing magic. 1167 | * 1168 | * ``` php 1169 | * 'value', 1172 | * 'field2' => 'another value', 1173 | * 'checkbox1' => true, 1174 | * // ... 1175 | * ]; 1176 | * $I->submitForm('//form[@id=my-form]', $form, 'submitButton'); 1177 | * // $I->amOnPage('/path/to/form-page') may be needed 1178 | * $I->seeInFormFields('//form[@id=my-form]', $form); 1179 | * ?> 1180 | * ``` 1181 | * 1182 | * @param $formSelector 1183 | * @param $params 1184 | * Conditional Assertion: Test won't be stopped on fail 1185 | * @see \Codeception\Module\WebDriver::seeInFormFields() 1186 | */ 1187 | public function canSeeInFormFields($formSelector, $params) { 1188 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInFormFields', func_get_args())); 1189 | } 1190 | /** 1191 | * [!] Method is generated. Documentation taken from corresponding module. 1192 | * 1193 | * Checks if the array of form parameters (name => value) are set on the form matched with the 1194 | * passed selector. 1195 | * 1196 | * ``` php 1197 | * seeInFormFields('form[name=myform]', [ 1199 | * 'input1' => 'value', 1200 | * 'input2' => 'other value', 1201 | * ]); 1202 | * ?> 1203 | * ``` 1204 | * 1205 | * For multi-select elements, or to check values of multiple elements with the same name, an 1206 | * array may be passed: 1207 | * 1208 | * ``` php 1209 | * seeInFormFields('.form-class', [ 1211 | * 'multiselect' => [ 1212 | * 'value1', 1213 | * 'value2', 1214 | * ], 1215 | * 'checkbox[]' => [ 1216 | * 'a checked value', 1217 | * 'another checked value', 1218 | * ], 1219 | * ]); 1220 | * ?> 1221 | * ``` 1222 | * 1223 | * Additionally, checkbox values can be checked with a boolean. 1224 | * 1225 | * ``` php 1226 | * seeInFormFields('#form-id', [ 1228 | * 'checkbox1' => true, // passes if checked 1229 | * 'checkbox2' => false, // passes if unchecked 1230 | * ]); 1231 | * ?> 1232 | * ``` 1233 | * 1234 | * Pair this with submitForm for quick testing magic. 1235 | * 1236 | * ``` php 1237 | * 'value', 1240 | * 'field2' => 'another value', 1241 | * 'checkbox1' => true, 1242 | * // ... 1243 | * ]; 1244 | * $I->submitForm('//form[@id=my-form]', $form, 'submitButton'); 1245 | * // $I->amOnPage('/path/to/form-page') may be needed 1246 | * $I->seeInFormFields('//form[@id=my-form]', $form); 1247 | * ?> 1248 | * ``` 1249 | * 1250 | * @param $formSelector 1251 | * @param $params 1252 | * @see \Codeception\Module\WebDriver::seeInFormFields() 1253 | */ 1254 | public function seeInFormFields($formSelector, $params) { 1255 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInFormFields', func_get_args())); 1256 | } 1257 | 1258 | 1259 | /** 1260 | * [!] Method is generated. Documentation taken from corresponding module. 1261 | * 1262 | * Checks if the array of form parameters (name => value) are not set on the form matched with 1263 | * the passed selector. 1264 | * 1265 | * ``` php 1266 | * dontSeeInFormFields('form[name=myform]', [ 1268 | * 'input1' => 'non-existent value', 1269 | * 'input2' => 'other non-existent value', 1270 | * ]); 1271 | * ?> 1272 | * ``` 1273 | * 1274 | * To check that an element hasn't been assigned any one of many values, an array can be passed 1275 | * as the value: 1276 | * 1277 | * ``` php 1278 | * dontSeeInFormFields('.form-class', [ 1280 | * 'fieldName' => [ 1281 | * 'This value shouldn\'t be set', 1282 | * 'And this value shouldn\'t be set', 1283 | * ], 1284 | * ]); 1285 | * ?> 1286 | * ``` 1287 | * 1288 | * Additionally, checkbox values can be checked with a boolean. 1289 | * 1290 | * ``` php 1291 | * dontSeeInFormFields('#form-id', [ 1293 | * 'checkbox1' => true, // fails if checked 1294 | * 'checkbox2' => false, // fails if unchecked 1295 | * ]); 1296 | * ?> 1297 | * ``` 1298 | * 1299 | * @param $formSelector 1300 | * @param $params 1301 | * Conditional Assertion: Test won't be stopped on fail 1302 | * @see \Codeception\Module\WebDriver::dontSeeInFormFields() 1303 | */ 1304 | public function cantSeeInFormFields($formSelector, $params) { 1305 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInFormFields', func_get_args())); 1306 | } 1307 | /** 1308 | * [!] Method is generated. Documentation taken from corresponding module. 1309 | * 1310 | * Checks if the array of form parameters (name => value) are not set on the form matched with 1311 | * the passed selector. 1312 | * 1313 | * ``` php 1314 | * dontSeeInFormFields('form[name=myform]', [ 1316 | * 'input1' => 'non-existent value', 1317 | * 'input2' => 'other non-existent value', 1318 | * ]); 1319 | * ?> 1320 | * ``` 1321 | * 1322 | * To check that an element hasn't been assigned any one of many values, an array can be passed 1323 | * as the value: 1324 | * 1325 | * ``` php 1326 | * dontSeeInFormFields('.form-class', [ 1328 | * 'fieldName' => [ 1329 | * 'This value shouldn\'t be set', 1330 | * 'And this value shouldn\'t be set', 1331 | * ], 1332 | * ]); 1333 | * ?> 1334 | * ``` 1335 | * 1336 | * Additionally, checkbox values can be checked with a boolean. 1337 | * 1338 | * ``` php 1339 | * dontSeeInFormFields('#form-id', [ 1341 | * 'checkbox1' => true, // fails if checked 1342 | * 'checkbox2' => false, // fails if unchecked 1343 | * ]); 1344 | * ?> 1345 | * ``` 1346 | * 1347 | * @param $formSelector 1348 | * @param $params 1349 | * @see \Codeception\Module\WebDriver::dontSeeInFormFields() 1350 | */ 1351 | public function dontSeeInFormFields($formSelector, $params) { 1352 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInFormFields', func_get_args())); 1353 | } 1354 | 1355 | 1356 | /** 1357 | * [!] Method is generated. Documentation taken from corresponding module. 1358 | * 1359 | * Selects an option in a select tag or in radio button group. 1360 | * 1361 | * ``` php 1362 | * selectOption('form select[name=account]', 'Premium'); 1364 | * $I->selectOption('form input[name=payment]', 'Monthly'); 1365 | * $I->selectOption('//form/select[@name=account]', 'Monthly'); 1366 | * ?> 1367 | * ``` 1368 | * 1369 | * Provide an array for the second argument to select multiple options: 1370 | * 1371 | * ``` php 1372 | * selectOption('Which OS do you use?', array('Windows','Linux')); 1374 | * ?> 1375 | * ``` 1376 | * 1377 | * @param $select 1378 | * @param $option 1379 | * @see \Codeception\Module\WebDriver::selectOption() 1380 | */ 1381 | public function selectOption($select, $option) { 1382 | return $this->getScenario()->runStep(new \Codeception\Step\Action('selectOption', func_get_args())); 1383 | } 1384 | 1385 | 1386 | /** 1387 | * [!] Method is generated. Documentation taken from corresponding module. 1388 | * 1389 | * 1390 | * @see \Codeception\Module\WebDriver::unselectOption() 1391 | */ 1392 | public function unselectOption($select, $option) { 1393 | return $this->getScenario()->runStep(new \Codeception\Step\Action('unselectOption', func_get_args())); 1394 | } 1395 | 1396 | 1397 | /** 1398 | * [!] Method is generated. Documentation taken from corresponding module. 1399 | * 1400 | * Ticks a checkbox. For radio buttons, use the `selectOption` method instead. 1401 | * 1402 | * ``` php 1403 | * checkOption('#agree'); 1405 | * ?> 1406 | * ``` 1407 | * 1408 | * @param $option 1409 | * @see \Codeception\Module\WebDriver::checkOption() 1410 | */ 1411 | public function checkOption($option) { 1412 | return $this->getScenario()->runStep(new \Codeception\Step\Action('checkOption', func_get_args())); 1413 | } 1414 | 1415 | 1416 | /** 1417 | * [!] Method is generated. Documentation taken from corresponding module. 1418 | * 1419 | * Unticks a checkbox. 1420 | * 1421 | * ``` php 1422 | * uncheckOption('#notify'); 1424 | * ?> 1425 | * ``` 1426 | * 1427 | * @param $option 1428 | * @see \Codeception\Module\WebDriver::uncheckOption() 1429 | */ 1430 | public function uncheckOption($option) { 1431 | return $this->getScenario()->runStep(new \Codeception\Step\Action('uncheckOption', func_get_args())); 1432 | } 1433 | 1434 | 1435 | /** 1436 | * [!] Method is generated. Documentation taken from corresponding module. 1437 | * 1438 | * Fills a text field or textarea with the given string. 1439 | * 1440 | * ``` php 1441 | * fillField("//input[@type='text']", "Hello World!"); 1443 | * $I->fillField(['name' => 'email'], 'jon@mail.com'); 1444 | * ?> 1445 | * ``` 1446 | * 1447 | * @param $field 1448 | * @param $value 1449 | * @see \Codeception\Module\WebDriver::fillField() 1450 | */ 1451 | public function fillField($field, $value) { 1452 | return $this->getScenario()->runStep(new \Codeception\Step\Action('fillField', func_get_args())); 1453 | } 1454 | 1455 | 1456 | /** 1457 | * [!] Method is generated. Documentation taken from corresponding module. 1458 | * 1459 | * Attaches a file relative to the Codeception data directory to the given file upload field. 1460 | * 1461 | * ``` php 1462 | * attachFile('input[@type="file"]', 'prices.xls'); 1465 | * ?> 1466 | * ``` 1467 | * 1468 | * @param $field 1469 | * @param $filename 1470 | * @see \Codeception\Module\WebDriver::attachFile() 1471 | */ 1472 | public function attachFile($field, $filename) { 1473 | return $this->getScenario()->runStep(new \Codeception\Step\Action('attachFile', func_get_args())); 1474 | } 1475 | 1476 | 1477 | /** 1478 | * [!] Method is generated. Documentation taken from corresponding module. 1479 | * 1480 | * Grabs all visible text from the current page. 1481 | * 1482 | * @return string 1483 | * @see \Codeception\Module\WebDriver::getVisibleText() 1484 | */ 1485 | public function getVisibleText() { 1486 | return $this->getScenario()->runStep(new \Codeception\Step\Action('getVisibleText', func_get_args())); 1487 | } 1488 | 1489 | 1490 | /** 1491 | * [!] Method is generated. Documentation taken from corresponding module. 1492 | * 1493 | * Finds and returns the text contents of the given element. 1494 | * If a fuzzy locator is used, the element is found using CSS, XPath, and by matching the full page source by regular expression. 1495 | * 1496 | * ``` php 1497 | * grabTextFrom('h1'); 1499 | * $heading = $I->grabTextFrom('descendant-or-self::h1'); 1500 | * $value = $I->grabTextFrom('~ 1502 | * ``` 1503 | * 1504 | * @param $cssOrXPathOrRegex 1505 | * 1506 | * @return mixed 1507 | * @see \Codeception\Module\WebDriver::grabTextFrom() 1508 | */ 1509 | public function grabTextFrom($cssOrXPathOrRegex) { 1510 | return $this->getScenario()->runStep(new \Codeception\Step\Action('grabTextFrom', func_get_args())); 1511 | } 1512 | 1513 | 1514 | /** 1515 | * [!] Method is generated. Documentation taken from corresponding module. 1516 | * 1517 | * Grabs the value of the given attribute value from the given element. 1518 | * Fails if element is not found. 1519 | * 1520 | * ``` php 1521 | * grabAttributeFrom('#tooltip', 'title'); 1523 | * ?> 1524 | * ``` 1525 | * 1526 | * 1527 | * @param $cssOrXpath 1528 | * @param $attribute 1529 | * 1530 | * @return mixed 1531 | * @see \Codeception\Module\WebDriver::grabAttributeFrom() 1532 | */ 1533 | public function grabAttributeFrom($cssOrXpath, $attribute) { 1534 | return $this->getScenario()->runStep(new \Codeception\Step\Action('grabAttributeFrom', func_get_args())); 1535 | } 1536 | 1537 | 1538 | /** 1539 | * [!] Method is generated. Documentation taken from corresponding module. 1540 | * 1541 | * Finds the value for the given form field. 1542 | * If a fuzzy locator is used, the field is found by field name, CSS, and XPath. 1543 | * 1544 | * ``` php 1545 | * grabValueFrom('Name'); 1547 | * $name = $I->grabValueFrom('input[name=username]'); 1548 | * $name = $I->grabValueFrom('descendant-or-self::form/descendant::input[@name = 'username']'); 1549 | * $name = $I->grabValueFrom(['name' => 'username']); 1550 | * ?> 1551 | * ``` 1552 | * 1553 | * @param $field 1554 | * 1555 | * @return mixed 1556 | * @see \Codeception\Module\WebDriver::grabValueFrom() 1557 | */ 1558 | public function grabValueFrom($field) { 1559 | return $this->getScenario()->runStep(new \Codeception\Step\Action('grabValueFrom', func_get_args())); 1560 | } 1561 | 1562 | 1563 | /** 1564 | * [!] Method is generated. Documentation taken from corresponding module. 1565 | * 1566 | * Grabs either the text content, or attribute values, of nodes 1567 | * matched by $cssOrXpath and returns them as an array. 1568 | * 1569 | * ```html 1570 | * First 1571 | * Second 1572 | * Third 1573 | * ``` 1574 | * 1575 | * ```php 1576 | * grabMultiple('a'); 1579 | * 1580 | * // would return ['#first', '#second', '#third'] 1581 | * $aLinks = $I->grabMultiple('a', 'href'); 1582 | * ?> 1583 | * ``` 1584 | * 1585 | * @param $cssOrXpath 1586 | * @param $attribute 1587 | * @return string[] 1588 | * @see \Codeception\Module\WebDriver::grabMultiple() 1589 | */ 1590 | public function grabMultiple($cssOrXpath, $attribute = null) { 1591 | return $this->getScenario()->runStep(new \Codeception\Step\Action('grabMultiple', func_get_args())); 1592 | } 1593 | 1594 | 1595 | /** 1596 | * [!] Method is generated. Documentation taken from corresponding module. 1597 | * 1598 | * Checks that the given element exists on the page and is visible. 1599 | * You can also specify expected attributes of this element. 1600 | * 1601 | * ``` php 1602 | * seeElement('.error'); 1604 | * $I->seeElement('//form/input[1]'); 1605 | * $I->seeElement('input', ['name' => 'login']); 1606 | * $I->seeElement('input', ['value' => '123456']); 1607 | * 1608 | * // strict locator in first arg, attributes in second 1609 | * $I->seeElement(['css' => 'form input'], ['name' => 'login']); 1610 | * ?> 1611 | * ``` 1612 | * 1613 | * @param $selector 1614 | * @param array $attributes 1615 | * @return 1616 | * Conditional Assertion: Test won't be stopped on fail 1617 | * @see \Codeception\Module\WebDriver::seeElement() 1618 | */ 1619 | public function canSeeElement($selector, $attributes = null) { 1620 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeElement', func_get_args())); 1621 | } 1622 | /** 1623 | * [!] Method is generated. Documentation taken from corresponding module. 1624 | * 1625 | * Checks that the given element exists on the page and is visible. 1626 | * You can also specify expected attributes of this element. 1627 | * 1628 | * ``` php 1629 | * seeElement('.error'); 1631 | * $I->seeElement('//form/input[1]'); 1632 | * $I->seeElement('input', ['name' => 'login']); 1633 | * $I->seeElement('input', ['value' => '123456']); 1634 | * 1635 | * // strict locator in first arg, attributes in second 1636 | * $I->seeElement(['css' => 'form input'], ['name' => 'login']); 1637 | * ?> 1638 | * ``` 1639 | * 1640 | * @param $selector 1641 | * @param array $attributes 1642 | * @return 1643 | * @see \Codeception\Module\WebDriver::seeElement() 1644 | */ 1645 | public function seeElement($selector, $attributes = null) { 1646 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeElement', func_get_args())); 1647 | } 1648 | 1649 | 1650 | /** 1651 | * [!] Method is generated. Documentation taken from corresponding module. 1652 | * 1653 | * Checks that the given element is invisible or not present on the page. 1654 | * You can also specify expected attributes of this element. 1655 | * 1656 | * ``` php 1657 | * dontSeeElement('.error'); 1659 | * $I->dontSeeElement('//form/input[1]'); 1660 | * $I->dontSeeElement('input', ['name' => 'login']); 1661 | * $I->dontSeeElement('input', ['value' => '123456']); 1662 | * ?> 1663 | * ``` 1664 | * 1665 | * @param $selector 1666 | * @param array $attributes 1667 | * Conditional Assertion: Test won't be stopped on fail 1668 | * @see \Codeception\Module\WebDriver::dontSeeElement() 1669 | */ 1670 | public function cantSeeElement($selector, $attributes = null) { 1671 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeElement', func_get_args())); 1672 | } 1673 | /** 1674 | * [!] Method is generated. Documentation taken from corresponding module. 1675 | * 1676 | * Checks that the given element is invisible or not present on the page. 1677 | * You can also specify expected attributes of this element. 1678 | * 1679 | * ``` php 1680 | * dontSeeElement('.error'); 1682 | * $I->dontSeeElement('//form/input[1]'); 1683 | * $I->dontSeeElement('input', ['name' => 'login']); 1684 | * $I->dontSeeElement('input', ['value' => '123456']); 1685 | * ?> 1686 | * ``` 1687 | * 1688 | * @param $selector 1689 | * @param array $attributes 1690 | * @see \Codeception\Module\WebDriver::dontSeeElement() 1691 | */ 1692 | public function dontSeeElement($selector, $attributes = null) { 1693 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeElement', func_get_args())); 1694 | } 1695 | 1696 | 1697 | /** 1698 | * [!] Method is generated. Documentation taken from corresponding module. 1699 | * 1700 | * Checks that the given element exists on the page, even it is invisible. 1701 | * 1702 | * ``` php 1703 | * seeElementInDOM('//form/input[type=hidden]'); 1705 | * ?> 1706 | * ``` 1707 | * 1708 | * @param $selector 1709 | * Conditional Assertion: Test won't be stopped on fail 1710 | * @see \Codeception\Module\WebDriver::seeElementInDOM() 1711 | */ 1712 | public function canSeeElementInDOM($selector, $attributes = null) { 1713 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeElementInDOM', func_get_args())); 1714 | } 1715 | /** 1716 | * [!] Method is generated. Documentation taken from corresponding module. 1717 | * 1718 | * Checks that the given element exists on the page, even it is invisible. 1719 | * 1720 | * ``` php 1721 | * seeElementInDOM('//form/input[type=hidden]'); 1723 | * ?> 1724 | * ``` 1725 | * 1726 | * @param $selector 1727 | * @see \Codeception\Module\WebDriver::seeElementInDOM() 1728 | */ 1729 | public function seeElementInDOM($selector, $attributes = null) { 1730 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeElementInDOM', func_get_args())); 1731 | } 1732 | 1733 | 1734 | /** 1735 | * [!] Method is generated. Documentation taken from corresponding module. 1736 | * 1737 | * Opposite of `seeElementInDOM`. 1738 | * 1739 | * @param $selector 1740 | * Conditional Assertion: Test won't be stopped on fail 1741 | * @see \Codeception\Module\WebDriver::dontSeeElementInDOM() 1742 | */ 1743 | public function cantSeeElementInDOM($selector, $attributes = null) { 1744 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeElementInDOM', func_get_args())); 1745 | } 1746 | /** 1747 | * [!] Method is generated. Documentation taken from corresponding module. 1748 | * 1749 | * Opposite of `seeElementInDOM`. 1750 | * 1751 | * @param $selector 1752 | * @see \Codeception\Module\WebDriver::dontSeeElementInDOM() 1753 | */ 1754 | public function dontSeeElementInDOM($selector, $attributes = null) { 1755 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeElementInDOM', func_get_args())); 1756 | } 1757 | 1758 | 1759 | /** 1760 | * [!] Method is generated. Documentation taken from corresponding module. 1761 | * 1762 | * Checks that there are a certain number of elements matched by the given locator on the page. 1763 | * 1764 | * ``` php 1765 | * seeNumberOfElements('tr', 10); 1767 | * $I->seeNumberOfElements('tr', [0,10]); //between 0 and 10 elements 1768 | * ?> 1769 | * ``` 1770 | * @param $selector 1771 | * @param mixed $expected : 1772 | * - string: strict number 1773 | * - array: range of numbers [0,10] 1774 | * Conditional Assertion: Test won't be stopped on fail 1775 | * @see \Codeception\Module\WebDriver::seeNumberOfElements() 1776 | */ 1777 | public function canSeeNumberOfElements($selector, $expected) { 1778 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeNumberOfElements', func_get_args())); 1779 | } 1780 | /** 1781 | * [!] Method is generated. Documentation taken from corresponding module. 1782 | * 1783 | * Checks that there are a certain number of elements matched by the given locator on the page. 1784 | * 1785 | * ``` php 1786 | * seeNumberOfElements('tr', 10); 1788 | * $I->seeNumberOfElements('tr', [0,10]); //between 0 and 10 elements 1789 | * ?> 1790 | * ``` 1791 | * @param $selector 1792 | * @param mixed $expected : 1793 | * - string: strict number 1794 | * - array: range of numbers [0,10] 1795 | * @see \Codeception\Module\WebDriver::seeNumberOfElements() 1796 | */ 1797 | public function seeNumberOfElements($selector, $expected) { 1798 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeNumberOfElements', func_get_args())); 1799 | } 1800 | 1801 | 1802 | /** 1803 | * [!] Method is generated. Documentation taken from corresponding module. 1804 | * 1805 | * 1806 | * Conditional Assertion: Test won't be stopped on fail 1807 | * @see \Codeception\Module\WebDriver::seeNumberOfElementsInDOM() 1808 | */ 1809 | public function canSeeNumberOfElementsInDOM($selector, $expected) { 1810 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeNumberOfElementsInDOM', func_get_args())); 1811 | } 1812 | /** 1813 | * [!] Method is generated. Documentation taken from corresponding module. 1814 | * 1815 | * 1816 | * @see \Codeception\Module\WebDriver::seeNumberOfElementsInDOM() 1817 | */ 1818 | public function seeNumberOfElementsInDOM($selector, $expected) { 1819 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeNumberOfElementsInDOM', func_get_args())); 1820 | } 1821 | 1822 | 1823 | /** 1824 | * [!] Method is generated. Documentation taken from corresponding module. 1825 | * 1826 | * Checks that the given option is selected. 1827 | * 1828 | * ``` php 1829 | * seeOptionIsSelected('#form input[name=payment]', 'Visa'); 1831 | * ?> 1832 | * ``` 1833 | * 1834 | * @param $selector 1835 | * @param $optionText 1836 | * 1837 | * @return mixed 1838 | * Conditional Assertion: Test won't be stopped on fail 1839 | * @see \Codeception\Module\WebDriver::seeOptionIsSelected() 1840 | */ 1841 | public function canSeeOptionIsSelected($selector, $optionText) { 1842 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeOptionIsSelected', func_get_args())); 1843 | } 1844 | /** 1845 | * [!] Method is generated. Documentation taken from corresponding module. 1846 | * 1847 | * Checks that the given option is selected. 1848 | * 1849 | * ``` php 1850 | * seeOptionIsSelected('#form input[name=payment]', 'Visa'); 1852 | * ?> 1853 | * ``` 1854 | * 1855 | * @param $selector 1856 | * @param $optionText 1857 | * 1858 | * @return mixed 1859 | * @see \Codeception\Module\WebDriver::seeOptionIsSelected() 1860 | */ 1861 | public function seeOptionIsSelected($selector, $optionText) { 1862 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeOptionIsSelected', func_get_args())); 1863 | } 1864 | 1865 | 1866 | /** 1867 | * [!] Method is generated. Documentation taken from corresponding module. 1868 | * 1869 | * Checks that the given option is not selected. 1870 | * 1871 | * ``` php 1872 | * dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); 1874 | * ?> 1875 | * ``` 1876 | * 1877 | * @param $selector 1878 | * @param $optionText 1879 | * 1880 | * @return mixed 1881 | * Conditional Assertion: Test won't be stopped on fail 1882 | * @see \Codeception\Module\WebDriver::dontSeeOptionIsSelected() 1883 | */ 1884 | public function cantSeeOptionIsSelected($selector, $optionText) { 1885 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeOptionIsSelected', func_get_args())); 1886 | } 1887 | /** 1888 | * [!] Method is generated. Documentation taken from corresponding module. 1889 | * 1890 | * Checks that the given option is not selected. 1891 | * 1892 | * ``` php 1893 | * dontSeeOptionIsSelected('#form input[name=payment]', 'Visa'); 1895 | * ?> 1896 | * ``` 1897 | * 1898 | * @param $selector 1899 | * @param $optionText 1900 | * 1901 | * @return mixed 1902 | * @see \Codeception\Module\WebDriver::dontSeeOptionIsSelected() 1903 | */ 1904 | public function dontSeeOptionIsSelected($selector, $optionText) { 1905 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeOptionIsSelected', func_get_args())); 1906 | } 1907 | 1908 | 1909 | /** 1910 | * [!] Method is generated. Documentation taken from corresponding module. 1911 | * 1912 | * Checks that the page title contains the given string. 1913 | * 1914 | * ``` php 1915 | * seeInTitle('Blog - Post #1'); 1917 | * ?> 1918 | * ``` 1919 | * 1920 | * @param $title 1921 | * 1922 | * @return mixed 1923 | * Conditional Assertion: Test won't be stopped on fail 1924 | * @see \Codeception\Module\WebDriver::seeInTitle() 1925 | */ 1926 | public function canSeeInTitle($title) { 1927 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInTitle', func_get_args())); 1928 | } 1929 | /** 1930 | * [!] Method is generated. Documentation taken from corresponding module. 1931 | * 1932 | * Checks that the page title contains the given string. 1933 | * 1934 | * ``` php 1935 | * seeInTitle('Blog - Post #1'); 1937 | * ?> 1938 | * ``` 1939 | * 1940 | * @param $title 1941 | * 1942 | * @return mixed 1943 | * @see \Codeception\Module\WebDriver::seeInTitle() 1944 | */ 1945 | public function seeInTitle($title) { 1946 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInTitle', func_get_args())); 1947 | } 1948 | 1949 | 1950 | /** 1951 | * [!] Method is generated. Documentation taken from corresponding module. 1952 | * 1953 | * Checks that the page title does not contain the given string. 1954 | * 1955 | * @param $title 1956 | * 1957 | * @return mixed 1958 | * Conditional Assertion: Test won't be stopped on fail 1959 | * @see \Codeception\Module\WebDriver::dontSeeInTitle() 1960 | */ 1961 | public function cantSeeInTitle($title) { 1962 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('dontSeeInTitle', func_get_args())); 1963 | } 1964 | /** 1965 | * [!] Method is generated. Documentation taken from corresponding module. 1966 | * 1967 | * Checks that the page title does not contain the given string. 1968 | * 1969 | * @param $title 1970 | * 1971 | * @return mixed 1972 | * @see \Codeception\Module\WebDriver::dontSeeInTitle() 1973 | */ 1974 | public function dontSeeInTitle($title) { 1975 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('dontSeeInTitle', func_get_args())); 1976 | } 1977 | 1978 | 1979 | /** 1980 | * [!] Method is generated. Documentation taken from corresponding module. 1981 | * 1982 | * Accepts the active JavaScript native popup window, as created by `window.alert`|`window.confirm`|`window.prompt`. 1983 | * Don't confuse popups with modal windows, as created by [various libraries](http://jster.net/category/windows-modals-popups). 1984 | * @see \Codeception\Module\WebDriver::acceptPopup() 1985 | */ 1986 | public function acceptPopup() { 1987 | return $this->getScenario()->runStep(new \Codeception\Step\Action('acceptPopup', func_get_args())); 1988 | } 1989 | 1990 | 1991 | /** 1992 | * [!] Method is generated. Documentation taken from corresponding module. 1993 | * 1994 | * Dismisses the active JavaScript popup, as created by `window.alert`|`window.confirm`|`window.prompt`. 1995 | * @see \Codeception\Module\WebDriver::cancelPopup() 1996 | */ 1997 | public function cancelPopup() { 1998 | return $this->getScenario()->runStep(new \Codeception\Step\Action('cancelPopup', func_get_args())); 1999 | } 2000 | 2001 | 2002 | /** 2003 | * [!] Method is generated. Documentation taken from corresponding module. 2004 | * 2005 | * Checks that the active JavaScript popup, as created by `window.alert`|`window.confirm`|`window.prompt`, contains the given string. 2006 | * 2007 | * @param $text 2008 | * Conditional Assertion: Test won't be stopped on fail 2009 | * @see \Codeception\Module\WebDriver::seeInPopup() 2010 | */ 2011 | public function canSeeInPopup($text) { 2012 | return $this->getScenario()->runStep(new \Codeception\Step\ConditionalAssertion('seeInPopup', func_get_args())); 2013 | } 2014 | /** 2015 | * [!] Method is generated. Documentation taken from corresponding module. 2016 | * 2017 | * Checks that the active JavaScript popup, as created by `window.alert`|`window.confirm`|`window.prompt`, contains the given string. 2018 | * 2019 | * @param $text 2020 | * @see \Codeception\Module\WebDriver::seeInPopup() 2021 | */ 2022 | public function seeInPopup($text) { 2023 | return $this->getScenario()->runStep(new \Codeception\Step\Assertion('seeInPopup', func_get_args())); 2024 | } 2025 | 2026 | 2027 | /** 2028 | * [!] Method is generated. Documentation taken from corresponding module. 2029 | * 2030 | * Enters text into a native JavaScript prompt popup, as created by `window.prompt`. 2031 | * 2032 | * @param $keys 2033 | * @see \Codeception\Module\WebDriver::typeInPopup() 2034 | */ 2035 | public function typeInPopup($keys) { 2036 | return $this->getScenario()->runStep(new \Codeception\Step\Action('typeInPopup', func_get_args())); 2037 | } 2038 | 2039 | 2040 | /** 2041 | * [!] Method is generated. Documentation taken from corresponding module. 2042 | * 2043 | * Reloads the current page. 2044 | * @see \Codeception\Module\WebDriver::reloadPage() 2045 | */ 2046 | public function reloadPage() { 2047 | return $this->getScenario()->runStep(new \Codeception\Step\Action('reloadPage', func_get_args())); 2048 | } 2049 | 2050 | 2051 | /** 2052 | * [!] Method is generated. Documentation taken from corresponding module. 2053 | * 2054 | * Moves back in history. 2055 | * @see \Codeception\Module\WebDriver::moveBack() 2056 | */ 2057 | public function moveBack() { 2058 | return $this->getScenario()->runStep(new \Codeception\Step\Action('moveBack', func_get_args())); 2059 | } 2060 | 2061 | 2062 | /** 2063 | * [!] Method is generated. Documentation taken from corresponding module. 2064 | * 2065 | * Moves forward in history. 2066 | * @see \Codeception\Module\WebDriver::moveForward() 2067 | */ 2068 | public function moveForward() { 2069 | return $this->getScenario()->runStep(new \Codeception\Step\Action('moveForward', func_get_args())); 2070 | } 2071 | 2072 | 2073 | /** 2074 | * [!] Method is generated. Documentation taken from corresponding module. 2075 | * 2076 | * Submits the given form on the page, optionally with the given form 2077 | * values. Give the form fields values as an array. Note that hidden fields 2078 | * can't be accessed. 2079 | * 2080 | * Skipped fields will be filled by their values from the page. 2081 | * You don't need to click the 'Submit' button afterwards. 2082 | * This command itself triggers the request to form's action. 2083 | * 2084 | * You can optionally specify what button's value to include 2085 | * in the request with the last parameter as an alternative to 2086 | * explicitly setting its value in the second parameter, as 2087 | * button values are not otherwise included in the request. 2088 | * 2089 | * Examples: 2090 | * 2091 | * ``` php 2092 | * submitForm('#login', [ 2094 | * 'login' => 'davert', 2095 | * 'password' => '123456' 2096 | * ]); 2097 | * // or 2098 | * $I->submitForm('#login', [ 2099 | * 'login' => 'davert', 2100 | * 'password' => '123456' 2101 | * ], 'submitButtonName'); 2102 | * 2103 | * ``` 2104 | * 2105 | * For example, given this sample "Sign Up" form: 2106 | * 2107 | * ``` html 2108 | *
2109 | * Login: 2110 | *
2111 | * Password: 2112 | *
2113 | * Do you agree to our terms? 2114 | *
2115 | * Select pricing plan: 2116 | * 2120 | * 2121 | *
2122 | * ``` 2123 | * 2124 | * You could write the following to submit it: 2125 | * 2126 | * ``` php 2127 | * submitForm( 2129 | * '#userForm', 2130 | * [ 2131 | * 'user[login]' => 'Davert', 2132 | * 'user[password]' => '123456', 2133 | * 'user[agree]' => true 2134 | * ], 2135 | * 'submitButton' 2136 | * ); 2137 | * ``` 2138 | * Note that "2" will be the submitted value for the "plan" field, as it is 2139 | * the selected option. 2140 | * 2141 | * Also note that this differs from PhpBrowser, in that 2142 | * ```'user' => [ 'login' => 'Davert' ]``` is not supported at the moment. 2143 | * Named array keys *must* be included in the name as above. 2144 | * 2145 | * Pair this with seeInFormFields for quick testing magic. 2146 | * 2147 | * ``` php 2148 | * 'value', 2151 | * 'field2' => 'another value', 2152 | * 'checkbox1' => true, 2153 | * // ... 2154 | * ]; 2155 | * $I->submitForm('//form[@id=my-form]', $form, 'submitButton'); 2156 | * // $I->amOnPage('/path/to/form-page') may be needed 2157 | * $I->seeInFormFields('//form[@id=my-form]', $form); 2158 | * ?> 2159 | * ``` 2160 | * 2161 | * Parameter values must be set to arrays for multiple input fields 2162 | * of the same name, or multi-select combo boxes. For checkboxes, 2163 | * either the string value can be used, or boolean values which will 2164 | * be replaced by the checkbox's value in the DOM. 2165 | * 2166 | * ``` php 2167 | * submitForm('#my-form', [ 2169 | * 'field1' => 'value', 2170 | * 'checkbox' => [ 2171 | * 'value of first checkbox', 2172 | * 'value of second checkbox, 2173 | * ], 2174 | * 'otherCheckboxes' => [ 2175 | * true, 2176 | * false, 2177 | * false 2178 | * ], 2179 | * 'multiselect' => [ 2180 | * 'first option value', 2181 | * 'second option value' 2182 | * ] 2183 | * ]); 2184 | * ?> 2185 | * ``` 2186 | * 2187 | * Mixing string and boolean values for a checkbox's value is not supported 2188 | * and may produce unexpected results. 2189 | * 2190 | * Field names ending in "[]" must be passed without the trailing square 2191 | * bracket characters, and must contain an array for its value. This allows 2192 | * submitting multiple values with the same name, consider: 2193 | * 2194 | * ```php 2195 | * $I->submitForm('#my-form', [ 2196 | * 'field[]' => 'value', 2197 | * 'field[]' => 'another value', // 'field[]' is already a defined key 2198 | * ]); 2199 | * ``` 2200 | * 2201 | * The solution is to pass an array value: 2202 | * 2203 | * ```php 2204 | * // this way both values are submitted 2205 | * $I->submitForm('#my-form', [ 2206 | * 'field' => [ 2207 | * 'value', 2208 | * 'another value', 2209 | * ] 2210 | * ]); 2211 | * ``` 2212 | * @param $selector 2213 | * @param $params 2214 | * @param $button 2215 | * @see \Codeception\Module\WebDriver::submitForm() 2216 | */ 2217 | public function submitForm($selector, $params, $button = null) { 2218 | return $this->getScenario()->runStep(new \Codeception\Step\Action('submitForm', func_get_args())); 2219 | } 2220 | 2221 | 2222 | /** 2223 | * [!] Method is generated. Documentation taken from corresponding module. 2224 | * 2225 | * Waits up to $timeout seconds for the given element to change. 2226 | * Element "change" is determined by a callback function which is called repeatedly until the return value evaluates to true. 2227 | * 2228 | * ``` php 2229 | * waitForElementChange('#menu', function(WebDriverElement $el) { 2232 | * return $el->isDisplayed(); 2233 | * }, 100); 2234 | * ?> 2235 | * ``` 2236 | * 2237 | * @param $element 2238 | * @param \Closure $callback 2239 | * @param int $timeout seconds 2240 | * @throws \Codeception\Exception\ElementNotFound 2241 | * @see \Codeception\Module\WebDriver::waitForElementChange() 2242 | */ 2243 | public function waitForElementChange($element, $callback, $timeout = null) { 2244 | return $this->getScenario()->runStep(new \Codeception\Step\Action('waitForElementChange', func_get_args())); 2245 | } 2246 | 2247 | 2248 | /** 2249 | * [!] Method is generated. Documentation taken from corresponding module. 2250 | * 2251 | * Waits up to $timeout seconds for an element to appear on the page. 2252 | * If the element doesn't appear, a timeout exception is thrown. 2253 | * 2254 | * ``` php 2255 | * waitForElement('#agree_button', 30); // secs 2257 | * $I->click('#agree_button'); 2258 | * ?> 2259 | * ``` 2260 | * 2261 | * @param $element 2262 | * @param int $timeout seconds 2263 | * @throws \Exception 2264 | * @see \Codeception\Module\WebDriver::waitForElement() 2265 | */ 2266 | public function waitForElement($element, $timeout = null) { 2267 | return $this->getScenario()->runStep(new \Codeception\Step\Action('waitForElement', func_get_args())); 2268 | } 2269 | 2270 | 2271 | /** 2272 | * [!] Method is generated. Documentation taken from corresponding module. 2273 | * 2274 | * Waits up to $timeout seconds for the given element to be visible on the page. 2275 | * If element doesn't appear, a timeout exception is thrown. 2276 | * 2277 | * ``` php 2278 | * waitForElementVisible('#agree_button', 30); // secs 2280 | * $I->click('#agree_button'); 2281 | * ?> 2282 | * ``` 2283 | * 2284 | * @param $element 2285 | * @param int $timeout seconds 2286 | * @throws \Exception 2287 | * @see \Codeception\Module\WebDriver::waitForElementVisible() 2288 | */ 2289 | public function waitForElementVisible($element, $timeout = null) { 2290 | return $this->getScenario()->runStep(new \Codeception\Step\Action('waitForElementVisible', func_get_args())); 2291 | } 2292 | 2293 | 2294 | /** 2295 | * [!] Method is generated. Documentation taken from corresponding module. 2296 | * 2297 | * Waits up to $timeout seconds for the given element to become invisible. 2298 | * If element stays visible, a timeout exception is thrown. 2299 | * 2300 | * ``` php 2301 | * waitForElementNotVisible('#agree_button', 30); // secs 2303 | * ?> 2304 | * ``` 2305 | * 2306 | * @param $element 2307 | * @param int $timeout seconds 2308 | * @throws \Exception 2309 | * @see \Codeception\Module\WebDriver::waitForElementNotVisible() 2310 | */ 2311 | public function waitForElementNotVisible($element, $timeout = null) { 2312 | return $this->getScenario()->runStep(new \Codeception\Step\Action('waitForElementNotVisible', func_get_args())); 2313 | } 2314 | 2315 | 2316 | /** 2317 | * [!] Method is generated. Documentation taken from corresponding module. 2318 | * 2319 | * Waits up to $timeout seconds for the given string to appear on the page. 2320 | * Can also be passed a selector to search in. 2321 | * If the given text doesn't appear, a timeout exception is thrown. 2322 | * 2323 | * ``` php 2324 | * waitForText('foo', 30); // secs 2326 | * $I->waitForText('foo', 30, '.title'); // secs 2327 | * ?> 2328 | * ``` 2329 | * 2330 | * @param string $text 2331 | * @param int $timeout seconds 2332 | * @param null $selector 2333 | * @throws \Exception 2334 | * @see \Codeception\Module\WebDriver::waitForText() 2335 | */ 2336 | public function waitForText($text, $timeout = null, $selector = null) { 2337 | return $this->getScenario()->runStep(new \Codeception\Step\Action('waitForText', func_get_args())); 2338 | } 2339 | 2340 | 2341 | /** 2342 | * [!] Method is generated. Documentation taken from corresponding module. 2343 | * 2344 | * Wait for $timeout seconds. 2345 | * 2346 | * @param int $timeout secs 2347 | * @throws \Codeception\Exception\TestRuntimeException 2348 | * @see \Codeception\Module\WebDriver::wait() 2349 | */ 2350 | public function wait($timeout) { 2351 | return $this->getScenario()->runStep(new \Codeception\Step\Action('wait', func_get_args())); 2352 | } 2353 | 2354 | 2355 | /** 2356 | * [!] Method is generated. Documentation taken from corresponding module. 2357 | * 2358 | * Low-level API method. 2359 | * If Codeception commands are not enough, this allows you to use Selenium WebDriver methods directly: 2360 | * 2361 | * ``` php 2362 | * $I->executeInSelenium(function(\Facebook\WebDriver\Remote\RemoteWebDriver $webdriver) { 2363 | * $webdriver->get('http://google.com'); 2364 | * }); 2365 | * ``` 2366 | * 2367 | * This runs in the context of the [RemoteWebDriver class](https://github.com/facebook/php-webdriver/blob/master/lib/remote/RemoteWebDriver.php). 2368 | * Try not to use this command on a regular basis. 2369 | * If Codeception lacks a feature you need, please implement it and submit a patch. 2370 | * 2371 | * @param callable $function 2372 | * @see \Codeception\Module\WebDriver::executeInSelenium() 2373 | */ 2374 | public function executeInSelenium($function) { 2375 | return $this->getScenario()->runStep(new \Codeception\Step\Action('executeInSelenium', func_get_args())); 2376 | } 2377 | 2378 | 2379 | /** 2380 | * [!] Method is generated. Documentation taken from corresponding module. 2381 | * 2382 | * Switch to another window identified by name. 2383 | * 2384 | * The window can only be identified by name. If the $name parameter is blank, the parent window will be used. 2385 | * 2386 | * Example: 2387 | * ``` html 2388 | * 2389 | * ``` 2390 | * 2391 | * ``` php 2392 | * click("Open window"); 2394 | * # switch to another window 2395 | * $I->switchToWindow("another_window"); 2396 | * # switch to parent window 2397 | * $I->switchToWindow(); 2398 | * ?> 2399 | * ``` 2400 | * 2401 | * If the window has no name, the only way to access it is via the `executeInSelenium()` method, like so: 2402 | * 2403 | * ``` php 2404 | * executeInSelenium(function (\Facebook\WebDriver\Remote\RemoteWebDriver $webdriver) { 2406 | * $handles=$webdriver->getWindowHandles(); 2407 | * $last_window = end($handles); 2408 | * $webdriver->switchTo()->window($last_window); 2409 | * }); 2410 | * ?> 2411 | * ``` 2412 | * 2413 | * @param string|null $name 2414 | * @see \Codeception\Module\WebDriver::switchToWindow() 2415 | */ 2416 | public function switchToWindow($name = null) { 2417 | return $this->getScenario()->runStep(new \Codeception\Step\Action('switchToWindow', func_get_args())); 2418 | } 2419 | 2420 | 2421 | /** 2422 | * [!] Method is generated. Documentation taken from corresponding module. 2423 | * 2424 | * Switch to another frame on the page. 2425 | * 2426 | * Example: 2427 | * ``` html 2428 | *