Merge branch 'master' of https://github.com/notgosu/yii2-app-basic into notgosu-master

This commit is contained in:
Alexander Makarov 2016-07-25 23:33:12 +03:00
commit 0c5eb8ba82
63 changed files with 3451 additions and 743 deletions

3
.gitignore vendored
View File

@ -25,3 +25,6 @@ composer.phar
phpunit.phar phpunit.phar
# local phpunit config # local phpunit config
/phpunit.xml /phpunit.xml
tests/_output/*
tests/_support/_generated

View File

@ -18,20 +18,12 @@ cache:
install: install:
- travis_retry composer self-update && composer --version - travis_retry composer self-update && composer --version
- travis_retry composer global require "fxp/composer-asset-plugin:~1.1.1" - travis_retry composer global require "fxp/composer-asset-plugin:~1.1.1"
- export PATH="$HOME/.composer/vendor/bin:$PATH" - travis_retry composer update --dev --prefer-dist --no-interaction
- travis_retry composer install --dev --prefer-dist --no-interaction
# codeception
- travis_retry composer global require "codeception/codeception=2.0.*" "codeception/specify=*" "codeception/verify=*"
# setup application: # setup application:
- | - |
sed -i "s/'cookieValidationKey' => ''/'cookieValidationKey' => 'testkey'/" config/web.php sed -i "s/'cookieValidationKey' => ''/'cookieValidationKey' => 'testkey'/" config/web.php
cd tests
codecept build
cd ..
script: script:
- | - |
cd web php -S localhost:8080 -t web > /dev/null 2>&1 &
php -S localhost:8080 > /dev/null 2>&1 & composer exec codecept run
cd ../tests
codecept run

View File

@ -100,3 +100,83 @@ return [
- Yii won't create the database for you, this has to be done manually before you can access it. - Yii won't create the database for you, this has to be done manually before you can access it.
- Check and edit the other files in the `config/` directory to customize your application as required. - Check and edit the other files in the `config/` directory to customize your application as required.
- Refer to the README in the `tests` directory for information specific to basic application tests. - Refer to the README in the `tests` directory for information specific to basic application tests.
TESTING
-------
Tests are located in `tests` directory, developed with [Codeception PHP Testing Framework](http://codeception.com/).
By default there are 3 test suites: `unit`, `functional` and `acceptance`. Tests can be executed by running
```
composer exec codecept run
```
This will execute unit and functional tests. Unit tests are testing the system components, while functional tests are for testing user interaction.
Acceptance tests are disabled by default as they require additional setup as they perform testing in real browser.
To execute acceptance tests do the following:
1. Rename `tests/acceptance.suite.yml.example` to `tests/acceptance.suite.yml` to enable suite configuration
2. Replace `codeception/base` package in `composer.json` with `codeception/codeception` to install full featured version of Codeception.
3. Update dependencies with Composer
```
composer update
```
4. Download [Selenium Server](http://www.seleniumhq.org/download/) and launch it:
```
java -jar java -jar ~/selenium-server-standalone-x.xx.x.jar
```
5. (Optional) Create `yii2_basic_tests` database and update it by applying migrations if you have them.
```
tests/bin/yii migrate
```
The database configuration can be found at `config/test_db.php`.
6. Start web server:
```
tests/bin/yii serve
```
7. Now you can run all available tests
```
# run all available tests
composer exec codecept run
# run acceptance tests
composer exec codecept run acceptance
# run only unit and functional tests
composer exec codecept run unit,functional
```
Code coverage support
---------------------
By default, code coverage is disabled in `codeception.yml` configuration file, you should uncomment needed rows to be able
to collect code coverage. You can run your tests and collect coverage with the following command:
```
#collect coverage for all tests
composer exec codecept run --coverage-html --coverage-xml
#collect coverage only for unit tests
composer exec codecept run unit --coverage-html --coverage-xml
#collect coverage for unit and functional tests
composer exec codecept run functional,unit --coverage-html --coverage-xml
```
You can see code coverage output under the `tests/_output` directory.

View File

@ -1,4 +1,19 @@
actor: Tester actor: Tester
paths:
tests: tests
log: tests/_output
data: tests/_data
helpers: tests/_support
settings:
bootstrap: _bootstrap.php
memory_limit: 1024M
colors: true
modules:
config:
Yii2:
configFile: 'config/test.php'
# To enable code coverage:
#coverage: #coverage:
# #c3_url: http://localhost:8080/index-test.php/ # #c3_url: http://localhost:8080/index-test.php/
# enabled: true # enabled: true
@ -19,18 +34,3 @@ actor: Tester
# - ../views/* # - ../views/*
# - ../web/* # - ../web/*
# - ../tests/* # - ../tests/*
paths:
tests: codeception
log: codeception/_output
data: codeception/_data
helpers: codeception/_support
settings:
bootstrap: _bootstrap.php
suite_class: \PHPUnit_Framework_TestSuite
memory_limit: 1024M
log: true
colors: true
config:
# the entry script URL (with host info) for functional and acceptance tests
# PLEASE ADJUST IT TO THE ACTUAL ENTRY SCRIPT URL
test_entry_url: http://localhost:8080/index-test.php

View File

@ -12,7 +12,7 @@
"irc": "irc://irc.freenode.net/yii", "irc": "irc://irc.freenode.net/yii",
"source": "https://github.com/yiisoft/yii2" "source": "https://github.com/yiisoft/yii2"
}, },
"minimum-stability": "dev", "minimum-stability": "stable",
"require": { "require": {
"php": ">=5.4.0", "php": ">=5.4.0",
"yiisoft/yii2": ">=2.0.5", "yiisoft/yii2": ">=2.0.5",
@ -20,7 +20,8 @@
"yiisoft/yii2-swiftmailer": "*" "yiisoft/yii2-swiftmailer": "*"
}, },
"require-dev": { "require-dev": {
"yiisoft/yii2-codeception": "*", "codeception/base": "^2.2.3",
"codeception/verify": "*",
"yiisoft/yii2-debug": "*", "yiisoft/yii2-debug": "*",
"yiisoft/yii2-gii": "*", "yiisoft/yii2-gii": "*",
"yiisoft/yii2-faker": "*", "yiisoft/yii2-faker": "*",

2845
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,5 @@
<?php <?php
Yii::setAlias('@tests', dirname(__DIR__) . '/tests/codeception');
$params = require(__DIR__ . '/params.php'); $params = require(__DIR__ . '/params.php');
$db = require(__DIR__ . '/db.php'); $db = require(__DIR__ . '/db.php');

35
config/test.php Normal file
View File

@ -0,0 +1,35 @@
<?php
$params = require(__DIR__ . '/params.php');
$dbParams = require(__DIR__ . '/test_db.php');
/**
* Application configuration shared by all test types
*/
return [
'id' => 'basic-tests',
'basePath' => dirname(__DIR__),
'language' => 'en-US',
'components' => [
'db' => $dbParams,
'mailer' => [
'useFileTransport' => true,
],
'urlManager' => [
'showScriptName' => true,
],
'user' => [
'identityClass' => 'app\models\User',
],
'request' => [
'cookieValidationKey' => 'test',
'enableCsrfValidation' => false,
// but if you absolutely need it set cookie domain to localhost
/*
'csrfCookie' => [
'domain' => 'localhost',
],
*/
],
],
'params' => $params,
];

6
config/test_db.php Normal file
View File

@ -0,0 +1,6 @@
<?php
$db = require(__DIR__ . '/db.php');
// test database! Important not to run tests on production or development databases
$db['dsn'] = 'mysql:host=localhost;dbname=yii2_basic_tests';
return $db;

View File

@ -1,128 +0,0 @@
This directory contains various tests for the basic application.
Tests in `codeception` directory are developed with [Codeception PHP Testing Framework](http://codeception.com/).
After creating the basic application, follow these steps to prepare for the tests:
1. Install Codeception if it's not yet installed:
```
composer global require "codeception/codeception=2.0.*"
composer global require "codeception/specify=*"
composer global require "codeception/verify=*"
```
If you've never used Composer for global packages run `composer global status`. It should output:
```
Changed current directory to <directory>
```
Then add `<directory>/vendor/bin` to you `PATH` environment variable. Now we're able to use `codecept` from command
line globally.
2. Install faker extension by running the following from template root directory where `composer.json` is:
```
composer require --dev "yiisoft/yii2-faker:*"
```
3. Create `yii2_basic_tests` database and update it by applying migrations (you may skip this step if you do not have created any migrations yet):
```
cd tests
codeception/bin/yii migrate
```
The command needs to be run in the `tests` directory.
The database configuration can be found at `tests/codeception/config/config.php`.
4. Build the test suites:
```
codecept build
```
5. In order to be able to run acceptance tests you need to start a webserver. The simplest way is to use built-in Yii
command:
```
./yii serve
```
6. Now you can run the tests with the following commands:
```
# run all available tests
codecept run
# run acceptance tests
codecept run acceptance
# run functional tests
codecept run functional
# run unit tests
codecept run unit
```
Fixtures Default Configuration
------------------------------
The `fixture` commands refer to the following `ActiveFixture` configuration by default:
- Fixtures path: `@tests/unit/fixtures`
- Fixtures data path: `@tests/unit/fixtures/data`
- Template files path: `@tests/unit/templates/fixtures`
- Namespace: `tests\unit\fixtures`
Where `@tests` refers to `@app/tests/codeception`.
Code coverage support
---------------------
By default, code coverage is disabled in `codeception.yml` configuration file, you should uncomment needed rows to be able
to collect code coverage. You can run your tests and collect coverage with the following command:
```
#collect coverage for all tests
codecept run --coverage-html --coverage-xml
#collect coverage only for unit tests
codecept run unit --coverage-html --coverage-xml
#collect coverage for unit and functional tests
codecept run functional,unit --coverage-html --coverage-xml
```
You can see code coverage output under the `tests/_output` directory.
###Remote code coverage
When you run your tests not in the same process where code coverage is collected, then you should uncomment `remote` option and its
related options, to be able to collect code coverage correctly. To setup remote code coverage you should follow [instructions](http://codeception.com/docs/11-Codecoverage)
from codeception site.
1. install `Codeception c3` remote support `composer require "codeception/c3:*"`;
2. copy `c3.php` file under your `web` directory;
3. include `c3.php` file in your `index-test.php` file before application run, so it can catch needed requests.
4. edit `c3.php` to update config file path (~ line 55) with `$config_file = realpath(__DIR__ . '/../tests/codeception.yml');`
Configuration options that are used by remote code coverage:
- c3_url: url pointing to entry script that includes `c3.php` file, so `Codeception` will be able to produce code coverage;
- remote: whether to enable remote code coverage or not;
- remote_config: path to the `codeception.yml` configuration file, from the directory where `c3.php` file is located. This is needed
so that `Codeception` can create itself instance and collect code coverage correctly.
By default `c3_url` and `remote_config` setup correctly, you only need to copy and include `c3.php` file in your `index-test.php`
After that you should be able to collect code coverage from tests that run through `PhpBrowser` or `WebDriver` with same command
as for other tests:
```
#collect coverage from remote
codecept run acceptance --coverage-html --coverage-xml
```
Please refer to [Codeception tutorial](http://codeception.com/docs/01-Introduction) for
more details about writing and running acceptance, functional and unit tests.

6
tests/_bootstrap.php Normal file
View File

@ -0,0 +1,6 @@
<?php
define('YII_ENV', 'test');
defined('YII_DEBUG') or define('YII_DEBUG', true);
require_once(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
require __DIR__ .'/../vendor/autoload.php';

View File

@ -0,0 +1,26 @@
<?php
/**
* Inherited Methods
* @method void wantToTest($text)
* @method void wantTo($text)
* @method void execute($callable)
* @method void expectTo($prediction)
* @method void expect($prediction)
* @method void amGoingTo($argumentation)
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
* @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
*
* @SuppressWarnings(PHPMD)
*/
class AcceptanceTester extends \Codeception\Actor
{
use _generated\AcceptanceTesterActions;
/**
* Define custom actions here
*/
}

View File

@ -0,0 +1,23 @@
<?php
/**
* Inherited Methods
* @method void wantToTest($text)
* @method void wantTo($text)
* @method void execute($callable)
* @method void expectTo($prediction)
* @method void expect($prediction)
* @method void amGoingTo($argumentation)
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
* @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
*
* @SuppressWarnings(PHPMD)
*/
class FunctionalTester extends \Codeception\Actor
{
use _generated\FunctionalTesterActions;
}

View File

@ -0,0 +1,26 @@
<?php
/**
* Inherited Methods
* @method void wantToTest($text)
* @method void wantTo($text)
* @method void execute($callable)
* @method void expectTo($prediction)
* @method void expect($prediction)
* @method void amGoingTo($argumentation)
* @method void am($role)
* @method void lookForwardTo($achieveValue)
* @method void comment($description)
* @method \Codeception\Lib\Friend haveFriend($name, $actorClass = NULL)
*
* @SuppressWarnings(PHPMD)
*/
class UnitTester extends \Codeception\Actor
{
use _generated\UnitTesterActions;
/**
* Define custom actions here
*/
}

View File

@ -0,0 +1,10 @@
class_name: AcceptanceTester
modules:
enabled:
- WebDriver:
url: http://127.0.0.1:8080/
browser: firefox
- Yii2:
part: orm
entryScript: index-test.php
cleanup: false

View File

@ -0,0 +1,11 @@
<?php
use yii\helpers\Url as Url;
class AboutCest
{
public function ensureThatAboutWorks(AcceptanceTester $I)
{
$I->amOnPage(Url::toRoute('/site/about'));
$I->see('About', 'h1');
}
}

View File

@ -0,0 +1,34 @@
<?php
use yii\helpers\Url as Url;
class ContactCest
{
public function _before(\AcceptanceTester $I)
{
$I->amOnPage(Url::toRoute('/site/contact'));
}
public function contactPageWorks(AcceptanceTester $I)
{
$I->wantTo('ensure that contact page works');
$I->see('Contact', 'h1');
}
public function contactFormCanBeSubmitted(AcceptanceTester $I)
{
$I->amGoingTo('submit contact form with correct data');
$I->fillField('#contactform-name', 'tester');
$I->fillField('#contactform-email', 'tester@example.com');
$I->fillField('#contactform-subject', 'test subject');
$I->fillField('#contactform-body', 'test content');
$I->fillField('#contactform-verifycode', 'testme');
$I->click('contact-button');
$I->wait(2); // wait for button to be clicked
$I->dontSeeElement('#contact-form');
$I->see('Thank you for contacting us. We will respond to you as soon as possible.');
}
}

View File

@ -0,0 +1,15 @@
<?php
class HomeCest
{
public function ensureThatHomePageWorks(AcceptanceTester $I)
{
$I->amOnPage('index.php?r=site%2Findex');
$I->see('My Company');
$I->seeLink('About');
$I->click('About');
$I->see('This is the About page.');
}
}

View File

@ -0,0 +1,20 @@
<?php
use yii\helpers\Url as Url;
class LoginCest
{
public function ensureThatLoginWorks(AcceptanceTester $I)
{
$I->amOnPage(Url::toRoute('/site/login'));
$I->see('Login', 'h1');
$I->amGoingTo('try to login with correct credentials');
$I->fillField('input[name="LoginForm[username]"]', 'admin');
$I->fillField('input[name="LoginForm[password]"]', 'admin');
$I->click('login-button');
$I->wait(2); // wait for button to be clicked
$I->expectTo('see user info');
$I->see('Logout');
}
}

View File

@ -0,0 +1 @@
<?php

29
tests/bin/yii Executable file
View File

@ -0,0 +1,29 @@
#!/usr/bin/env php
<?php
/**
* Yii console bootstrap file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'test');
require(__DIR__ . '/vendor/autoload.php');
require(__DIR__ . '/vendor/yiisoft/yii2/Yii.php');
$config = yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/config/console.php'),
[
'components' => [
'db' => require(__DIR__ . '/config/test_db.php')
]
]
);
$application = new yii\console\Application($config);
$exitCode = $application->run();
exit($exitCode);

View File

@ -1,4 +0,0 @@
# these files are auto generated by codeception build
/unit/UnitTester.php
/functional/FunctionalTester.php
/acceptance/AcceptanceTester.php

View File

@ -1,23 +0,0 @@
<?php
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'test');
defined('YII_TEST_ENTRY_URL') or define('YII_TEST_ENTRY_URL', parse_url(\Codeception\Configuration::config()['config']['test_entry_url'], PHP_URL_PATH));
defined('YII_TEST_ENTRY_FILE') or define('YII_TEST_ENTRY_FILE', dirname(dirname(__DIR__)) . '/web/index-test.php');
require_once(__DIR__ . '/../../vendor/autoload.php');
require_once(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
$_SERVER['SCRIPT_FILENAME'] = YII_TEST_ENTRY_FILE;
$_SERVER['SCRIPT_NAME'] = YII_TEST_ENTRY_URL;
$_SERVER['SERVER_NAME'] = parse_url(\Codeception\Configuration::config()['config']['test_entry_url'], PHP_URL_HOST);
$_SERVER['SERVER_PORT'] = parse_url(\Codeception\Configuration::config()['config']['test_entry_url'], PHP_URL_PORT) ?: '80';
Yii::setAlias('@tests', dirname(__DIR__));
/**
* this configure codeception specify to not deep clone objects properties
* it can be configure localy in your tests
* @see https://github.com/Codeception/Specify/tree/master/docs
*/
\Codeception\Specify\Config::setDeepClone(false);

View File

@ -1,14 +0,0 @@
<?php
namespace tests\codeception\_pages;
use yii\codeception\BasePage;
/**
* Represents about page
* @property \AcceptanceTester|\FunctionalTester $actor
*/
class AboutPage extends BasePage
{
public $route = 'site/about';
}

View File

@ -1,26 +0,0 @@
<?php
namespace tests\codeception\_pages;
use yii\codeception\BasePage;
/**
* Represents contact page
* @property \AcceptanceTester|\FunctionalTester $actor
*/
class ContactPage extends BasePage
{
public $route = 'site/contact';
/**
* @param array $contactData
*/
public function submit(array $contactData)
{
foreach ($contactData as $field => $value) {
$inputType = $field === 'body' ? 'textarea' : 'input';
$this->actor->fillField($inputType . '[name="ContactForm[' . $field . ']"]', $value);
}
$this->actor->click('contact-button');
}
}

View File

@ -1,25 +0,0 @@
<?php
namespace tests\codeception\_pages;
use yii\codeception\BasePage;
/**
* Represents login page
* @property \AcceptanceTester|\FunctionalTester $actor
*/
class LoginPage extends BasePage
{
public $route = 'site/login';
/**
* @param string $username
* @param string $password
*/
public function login($username, $password)
{
$this->actor->fillField('input[name="LoginForm[username]"]', $username);
$this->actor->fillField('input[name="LoginForm[password]"]', $password);
$this->actor->click('login-button');
}
}

View File

@ -1,27 +0,0 @@
# Codeception Test Suite Configuration
# suite for acceptance tests.
# perform tests in browser using the Selenium-like tools.
# powered by Mink (http://mink.behat.org).
# (tip: that's what your customer will see).
# (tip: test your ajax and javascript by one of Mink drivers).
# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.
class_name: AcceptanceTester
modules:
enabled:
- PhpBrowser
# you can use WebDriver instead of PhpBrowser to test javascript and ajax.
# This will require you to install selenium. See http://codeception.com/docs/03-AcceptanceTests#selenium-webdriver
# "restart" option is used by the WebDriver to start each time per test-file new session and cookies,
# it is useful if you want to login in your app in each test.
# - WebDriver
config:
PhpBrowser:
# PLEASE ADJUST IT TO THE ACTUAL ENTRY POINT WITHOUT PATH INFO
url: http://localhost:8080
# WebDriver:
# url: http://localhost:8080
# browser: firefox
# restart: true

View File

@ -1,10 +0,0 @@
<?php
use tests\codeception\_pages\AboutPage;
/* @var $scenario Codeception\Scenario */
$I = new AcceptanceTester($scenario);
$I->wantTo('ensure that about works');
AboutPage::openBy($I);
$I->see('About', 'h1');

View File

@ -1,57 +0,0 @@
<?php
use tests\codeception\_pages\ContactPage;
/* @var $scenario Codeception\Scenario */
$I = new AcceptanceTester($scenario);
$I->wantTo('ensure that contact works');
$contactPage = ContactPage::openBy($I);
$I->see('Contact', 'h1');
$I->amGoingTo('submit contact form with no data');
$contactPage->submit([]);
if (method_exists($I, 'wait')) {
$I->wait(3); // only for selenium
}
$I->expectTo('see validations errors');
$I->see('Contact', 'h1');
$I->see('Name cannot be blank');
$I->see('Email cannot be blank');
$I->see('Subject cannot be blank');
$I->see('Body cannot be blank');
$I->see('The verification code is incorrect');
$I->amGoingTo('submit contact form with not correct email');
$contactPage->submit([
'name' => 'tester',
'email' => 'tester.email',
'subject' => 'test subject',
'body' => 'test content',
'verifyCode' => 'testme',
]);
if (method_exists($I, 'wait')) {
$I->wait(3); // only for selenium
}
$I->expectTo('see that email address is wrong');
$I->dontSee('Name cannot be blank', '.help-inline');
$I->see('Email is not a valid email address.');
$I->dontSee('Subject cannot be blank', '.help-inline');
$I->dontSee('Body cannot be blank', '.help-inline');
$I->dontSee('The verification code is incorrect', '.help-inline');
$I->amGoingTo('submit contact form with correct data');
$contactPage->submit([
'name' => 'tester',
'email' => 'tester@example.com',
'subject' => 'test subject',
'body' => 'test content',
'verifyCode' => 'testme',
]);
if (method_exists($I, 'wait')) {
$I->wait(3); // only for selenium
}
$I->dontSeeElement('#contact-form');
$I->see('Thank you for contacting us. We will respond to you as soon as possible.');

View File

@ -1,11 +0,0 @@
<?php
/* @var $scenario Codeception\Scenario */
$I = new AcceptanceTester($scenario);
$I->wantTo('ensure that home page works');
$I->amOnPage(Yii::$app->homeUrl);
$I->see('My Company');
$I->seeLink('About');
$I->click('About');
$I->see('This is the About page.');

View File

@ -1,37 +0,0 @@
<?php
use tests\codeception\_pages\LoginPage;
/* @var $scenario Codeception\Scenario */
$I = new AcceptanceTester($scenario);
$I->wantTo('ensure that login works');
$loginPage = LoginPage::openBy($I);
$I->see('Login', 'h1');
$I->amGoingTo('try to login with empty credentials');
$loginPage->login('', '');
if (method_exists($I, 'wait')) {
$I->wait(3); // only for selenium
}
$I->expectTo('see validations errors');
$I->see('Username cannot be blank.');
$I->see('Password cannot be blank.');
$I->amGoingTo('try to login with wrong credentials');
$loginPage->login('admin', 'wrong');
if (method_exists($I, 'wait')) {
$I->wait(3); // only for selenium
}
$I->expectTo('see validations errors');
$I->see('Incorrect username or password.');
$I->amGoingTo('try to login with correct credentials');
$loginPage->login('admin', 'admin');
if (method_exists($I, 'wait')) {
$I->wait(3); // only for selenium
}
$I->expectTo('see user info');
$I->see('Logout (admin)');

View File

@ -1,2 +0,0 @@
<?php
new yii\web\Application(require(dirname(__DIR__) . '/config/acceptance.php'));

View File

@ -1,10 +0,0 @@
<?php
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'test');
defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', dirname(dirname(dirname(__DIR__))));
require(YII_APP_BASE_PATH . '/vendor/autoload.php');
require(YII_APP_BASE_PATH . '/vendor/yiisoft/yii2/Yii.php');
Yii::setAlias('@tests', dirname(dirname(__DIR__)));

View File

@ -1,20 +0,0 @@
#!/usr/bin/env php
<?php
/**
* Yii console bootstrap file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
require_once __DIR__ . '/_bootstrap.php';
$config = yii\helpers\ArrayHelper::merge(
require(YII_APP_BASE_PATH . '/config/console.php'),
require(__DIR__ . '/../config/config.php')
);
$application = new yii\console\Application($config);
$exitCode = $application->run();
exit($exitCode);

View File

@ -1,11 +0,0 @@
<?php
/**
* Application configuration for acceptance tests
*/
return yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/../../../config/web.php'),
require(__DIR__ . '/config.php'),
[
]
);

View File

@ -1,26 +0,0 @@
<?php
/**
* Application configuration shared by all test types
*/
return [
'language' => 'en-US',
'controllerMap' => [
'fixture' => [
'class' => 'yii\faker\FixtureController',
'fixtureDataPath' => '@tests/codeception/fixtures',
'templatePath' => '@tests/codeception/templates',
'namespace' => 'tests\codeception\fixtures',
],
],
'components' => [
'db' => [
'dsn' => 'mysql:host=localhost;dbname=yii2_basic_tests',
],
'mailer' => [
'useFileTransport' => true,
],
'urlManager' => [
'showScriptName' => true,
],
],
];

View File

@ -1,25 +0,0 @@
<?php
$_SERVER['SCRIPT_FILENAME'] = YII_TEST_ENTRY_FILE;
$_SERVER['SCRIPT_NAME'] = YII_TEST_ENTRY_URL;
/**
* Application configuration for functional tests
*/
return yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/../../../config/web.php'),
require(__DIR__ . '/config.php'),
[
'components' => [
'request' => [
// it's not recommended to run functional tests with CSRF validation enabled
'enableCsrfValidation' => false,
// but if you absolutely need it set cookie domain to localhost
/*
'csrfCookie' => [
'domain' => 'localhost',
],
*/
],
],
]
);

View File

@ -1,11 +0,0 @@
<?php
/**
* Application configuration for unit tests
*/
return yii\helpers\ArrayHelper::merge(
require(__DIR__ . '/../../../config/web.php'),
require(__DIR__ . '/config.php'),
[
]
);

View File

@ -1,10 +0,0 @@
<?php
use tests\codeception\_pages\AboutPage;
/* @var $scenario Codeception\Scenario */
$I = new FunctionalTester($scenario);
$I->wantTo('ensure that about works');
AboutPage::openBy($I);
$I->see('About', 'h1');

View File

@ -1,48 +0,0 @@
<?php
use tests\codeception\_pages\ContactPage;
/* @var $scenario Codeception\Scenario */
$I = new FunctionalTester($scenario);
$I->wantTo('ensure that contact works');
$contactPage = ContactPage::openBy($I);
$I->see('Contact', 'h1');
$I->amGoingTo('submit contact form with no data');
$contactPage->submit([]);
$I->expectTo('see validations errors');
$I->see('Contact', 'h1');
$I->see('Name cannot be blank');
$I->see('Email cannot be blank');
$I->see('Subject cannot be blank');
$I->see('Body cannot be blank');
$I->see('The verification code is incorrect');
$I->amGoingTo('submit contact form with not correct email');
$contactPage->submit([
'name' => 'tester',
'email' => 'tester.email',
'subject' => 'test subject',
'body' => 'test content',
'verifyCode' => 'testme',
]);
$I->expectTo('see that email address is wrong');
$I->dontSee('Name cannot be blank', '.help-inline');
$I->see('Email is not a valid email address.');
$I->dontSee('Subject cannot be blank', '.help-inline');
$I->dontSee('Body cannot be blank', '.help-inline');
$I->dontSee('The verification code is incorrect', '.help-inline');
$I->amGoingTo('submit contact form with correct data');
$contactPage->submit([
'name' => 'tester',
'email' => 'tester@example.com',
'subject' => 'test subject',
'body' => 'test content',
'verifyCode' => 'testme',
]);
$I->dontSeeElement('#contact-form');
$I->see('Thank you for contacting us. We will respond to you as soon as possible.');

View File

@ -1,11 +0,0 @@
<?php
/* @var $scenario Codeception\Scenario */
$I = new FunctionalTester($scenario);
$I->wantTo('ensure that home page works');
$I->amOnPage(Yii::$app->homeUrl);
$I->see('My Company');
$I->seeLink('About');
$I->click('About');
$I->see('This is the About page.');

View File

@ -1,28 +0,0 @@
<?php
use tests\codeception\_pages\LoginPage;
/* @var $scenario Codeception\Scenario */
$I = new FunctionalTester($scenario);
$I->wantTo('ensure that login works');
$loginPage = LoginPage::openBy($I);
$I->see('Login', 'h1');
$I->amGoingTo('try to login with empty credentials');
$loginPage->login('', '');
$I->expectTo('see validations errors');
$I->see('Username cannot be blank.');
$I->see('Password cannot be blank.');
$I->amGoingTo('try to login with wrong credentials');
$loginPage->login('admin', 'wrong');
$I->expectTo('see validations errors');
$I->see('Incorrect username or password.');
$I->amGoingTo('try to login with correct credentials');
$loginPage->login('admin', 'admin');
$I->expectTo('see user info');
$I->see('Logout (admin)');

View File

@ -1,2 +0,0 @@
<?php
new yii\web\Application(require(dirname(__DIR__) . '/config/functional.php'));

View File

@ -1,2 +0,0 @@
*
!.gitignore

View File

@ -1,63 +0,0 @@
<?php
namespace tests\codeception\unit\models;
use app\models\ContactForm;
use Yii;
use yii\codeception\TestCase;
use Codeception\Specify;
class ContactFormTest extends TestCase
{
use Specify;
protected function setUp()
{
parent::setUp();
Yii::$app->mailer->fileTransportCallback = function ($mailer, $message) {
return 'testing_message.eml';
};
}
protected function tearDown()
{
unlink($this->getMessageFile());
parent::tearDown();
}
public function testContact()
{
/** @var ContactForm $model */
$model = $this->getMockBuilder('app\models\ContactForm')
->setMethods(['validate'])
->getMock();
$model->expects($this->once())->method('validate')->will($this->returnValue(true));
$model->attributes = [
'name' => 'Tester',
'email' => 'tester@example.com',
'subject' => 'very important letter subject',
'body' => 'body of current message',
];
$this->specify('email should be send', function () use ($model) {
expect('ContactForm::contact() should return true', $model->contact('admin@example.com'))->true();
expect('email file should exist', file_exists($this->getMessageFile()))->true();
});
$this->specify('message should contain correct data', function () use ($model) {
$emailMessage = file_get_contents($this->getMessageFile());
expect('email should contain user name', $emailMessage)->contains($model->name);
expect('email should contain sender email', $emailMessage)->contains($model->email);
expect('email should contain subject', $emailMessage)->contains($model->subject);
expect('email should contain body', $emailMessage)->contains($model->body);
});
}
private function getMessageFile()
{
return Yii::getAlias(Yii::$app->mailer->fileTransportPath) . '/testing_message.eml';
}
}

View File

@ -1,61 +0,0 @@
<?php
namespace tests\codeception\unit\models;
use Yii;
use yii\codeception\TestCase;
use app\models\LoginForm;
use Codeception\Specify;
class LoginFormTest extends TestCase
{
use Specify;
protected function tearDown()
{
Yii::$app->user->logout();
parent::tearDown();
}
public function testLoginNoUser()
{
$model = new LoginForm([
'username' => 'not_existing_username',
'password' => 'not_existing_password',
]);
$this->specify('user should not be able to login, when there is no identity', function () use ($model) {
expect('model should not login user', $model->login())->false();
expect('user should not be logged in', Yii::$app->user->isGuest)->true();
});
}
public function testLoginWrongPassword()
{
$model = new LoginForm([
'username' => 'demo',
'password' => 'wrong_password',
]);
$this->specify('user should not be able to login with wrong password', function () use ($model) {
expect('model should not login user', $model->login())->false();
expect('error message should be set', $model->errors)->hasKey('password');
expect('user should not be logged in', Yii::$app->user->isGuest)->true();
});
}
public function testLoginCorrect()
{
$model = new LoginForm([
'username' => 'demo',
'password' => 'demo',
]);
$this->specify('user should be able to login with correct credentials', function () use ($model) {
expect('model should login user', $model->login())->true();
expect('error message should not be set', $model->errors)->hasntKey('password');
expect('user should be logged in', Yii::$app->user->isGuest)->false();
});
}
}

View File

@ -1,17 +0,0 @@
<?php
namespace tests\codeception\unit\models;
use yii\codeception\TestCase;
class UserTest extends TestCase
{
protected function setUp()
{
parent::setUp();
// uncomment the following to load fixtures for user table
//$this->loadFixtures(['user']);
}
// TODO add test methods here
}

View File

@ -11,6 +11,3 @@ modules:
enabled: enabled:
- Filesystem - Filesystem
- Yii2 - Yii2
config:
Yii2:
configFile: 'codeception/config/functional.php'

View File

@ -0,0 +1,56 @@
<?php
class ContactFormCest
{
public function _before(\FunctionalTester $I)
{
$I->amOnPage(['site/contact']);
}
public function openContactPage(\FunctionalTester $I)
{
$I->see('Contact', 'h1');
}
public function submitEmptyForm(\FunctionalTester $I)
{
$I->submitForm('#contact-form', []);
$I->expectTo('see validations errors');
$I->see('Contact', 'h1');
$I->see('Name cannot be blank');
$I->see('Email cannot be blank');
$I->see('Subject cannot be blank');
$I->see('Body cannot be blank');
$I->see('The verification code is incorrect');
}
public function submitFormWithIncorrectEmail(\FunctionalTester $I)
{
$I->submitForm('#contact-form', [
'ContactForm[name]' => 'tester',
'ContactForm[email]' => 'tester.email',
'ContactForm[subject]' => 'test subject',
'ContactForm[body]' => 'test content',
'ContactForm[verifyCode]' => 'testme',
]);
$I->expectTo('see that email address is wrong');
$I->dontSee('Name cannot be blank', '.help-inline');
$I->see('Email is not a valid email address.');
$I->dontSee('Subject cannot be blank', '.help-inline');
$I->dontSee('Body cannot be blank', '.help-inline');
$I->dontSee('The verification code is incorrect', '.help-inline');
}
public function submitFormSuccessfully(\FunctionalTester $I)
{
$I->submitForm('#contact-form', [
'ContactForm[name]' => 'tester',
'ContactForm[email]' => 'tester@example.com',
'ContactForm[subject]' => 'test subject',
'ContactForm[body]' => 'test content',
'ContactForm[verifyCode]' => 'testme',
]);
$I->seeEmailIsSent();
$I->dontSeeElement('#contact-form');
$I->see('Thank you for contacting us. We will respond to you as soon as possible.');
}
}

View File

@ -0,0 +1,58 @@
<?php
class LoginFormCest
{
public function _before(\FunctionalTester $I)
{
$I->amOnRoute('site/login');
}
public function openLoginPage(\FunctionalTester $I)
{
$I->see('Login', 'h1');
}
// demonstrates `amLoggedInAs` method
public function internalLoginById(\FunctionalTester $I)
{
$I->amLoggedInAs(100);
$I->amOnPage('/');
$I->see('Logout (admin)');
}
// demonstrates `amLoggedInAs` method
public function internalLoginByInstance(\FunctionalTester $I)
{
$I->amLoggedInAs(\app\models\User::findByUsername('admin'));
$I->amOnPage('/');
$I->see('Logout (admin)');
}
public function loginWithEmptyCredentials(\FunctionalTester $I)
{
$I->submitForm('#login-form', []);
$I->expectTo('see validations errors');
$I->see('Username cannot be blank.');
$I->see('Password cannot be blank.');
}
public function loginWithWrongCredentials(\FunctionalTester $I)
{
$I->submitForm('#login-form', [
'LoginForm[username]' => 'admin',
'LoginForm[password]' => 'wrong',
]);
$I->expectTo('see validations errors');
$I->see('Incorrect username or password.');
}
public function loginSuccessfully(\FunctionalTester $I)
{
$I->submitForm('#login-form', [
'LoginForm[username]' => 'admin',
'LoginForm[password]' => 'admin',
]);
$I->see('Logout (admin)');
$I->dontSeeElement('form#login-form');
}
}

View File

@ -0,0 +1 @@
<?php

View File

@ -4,3 +4,8 @@
# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES. # RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.
class_name: UnitTester class_name: UnitTester
modules:
enabled:
- Asserts
- Yii2:
part: [orm, email]

View File

@ -0,0 +1,45 @@
<?php
namespace tests\models;
use app\models\ContactForm;
class ContactFormTest extends \Codeception\Test\Unit
{
private $model;
/**
* @var \UnitTester
*/
public $tester;
public function testEmailIsSentOnContact()
{
/** @var ContactForm $model */
$this->model = $this->getMockBuilder('app\models\ContactForm')
->setMethods(['validate'])
->getMock();
$this->model->expects($this->once())
->method('validate')
->will($this->returnValue(true));
$this->model->attributes = [
'name' => 'Tester',
'email' => 'tester@example.com',
'subject' => 'very important letter subject',
'body' => 'body of current message',
];
expect_that($this->model->contact('admin@example.com'));
// using Yii2 module actions to check email was sent
$this->tester->seeEmailIsSent();
$emailMessage = $this->tester->grabLastSentEmail();
expect('valid email is sent', $emailMessage)->isInstanceOf('yii\mail\MessageInterface');
expect($emailMessage->getTo())->hasKey('admin@example.com');
expect($emailMessage->getFrom())->hasKey('tester@example.com');
expect($emailMessage->getSubject())->equals('very important letter subject');
expect($emailMessage->toString())->contains('body of current message');
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace tests\models;
use app\models\LoginForm;
use Codeception\Specify;
class LoginFormTest extends \Codeception\Test\Unit
{
private $model;
protected function _after()
{
\Yii::$app->user->logout();
}
public function testLoginNoUser()
{
$this->model = new LoginForm([
'username' => 'not_existing_username',
'password' => 'not_existing_password',
]);
expect_not($this->model->login());
expect_that(\Yii::$app->user->isGuest);
}
public function testLoginWrongPassword()
{
$this->model = new LoginForm([
'username' => 'demo',
'password' => 'wrong_password',
]);
expect_not($this->model->login());
expect_that(\Yii::$app->user->isGuest);
expect($this->model->errors)->hasKey('password');
}
public function testLoginCorrect()
{
$this->model = new LoginForm([
'username' => 'demo',
'password' => 'demo',
]);
expect_that($this->model->login());
expect_not(\Yii::$app->user->isGuest);
expect($this->model->errors)->hasntKey('password');
}
}

View File

@ -0,0 +1,42 @@
<?php
namespace tests\models;
use app\models\User;
class UserTest extends \Codeception\Test\Unit
{
public function testFindUserById()
{
expect_that($user = User::findIdentity(100));
expect($user->username)->equals('admin');
expect_not(User::findIdentity(999));
}
public function testFindUserByAccessToken()
{
expect_that($user = User::findIdentityByAccessToken('100-token'));
expect($user->username)->equals('admin');
expect_not(User::findIdentityByAccessToken('non-existing'));
}
public function testFindUserByUsername()
{
expect_that($user = User::findByUsername('admin'));
expect_not(User::findByUsername('not-admin'));
}
/**
* @depends testFindUserByUsername
*/
public function testValidateUser($user)
{
$user = User::findByUsername('admin');
expect_that($user->validateAuthKey('test100key'));
expect_not($user->validateAuthKey('test102key'));
expect_that($user->validatePassword('admin'));
expect_not($user->validatePassword('123456'));
}
}

View File

@ -11,6 +11,6 @@ defined('YII_ENV') or define('YII_ENV', 'test');
require(__DIR__ . '/../vendor/autoload.php'); require(__DIR__ . '/../vendor/autoload.php');
require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php'); require(__DIR__ . '/../vendor/yiisoft/yii2/Yii.php');
$config = require(__DIR__ . '/../tests/codeception/config/acceptance.php'); $config = require(__DIR__ . '/../config/test.php');
(new yii\web\Application($config))->run(); (new yii\web\Application($config))->run();