From 1406ab78f21dd1ceb8dab63772d76973509852e9 Mon Sep 17 00:00:00 2001
From: Mark <mark.github@yandex.ru>
Date: Sun, 16 Feb 2014 19:10:03 +0400
Subject: [PATCH] added codeception tests to frontend

---
 apps/advanced/frontend/codeception.yml                                    | 18 ++++++++++++++++++
 apps/advanced/frontend/tests/_bootstrap.php                               | 23 +++++++++++++++++++++++
 apps/advanced/frontend/tests/_config.php                                  | 14 ++++++++++++++
 apps/advanced/frontend/tests/_console.php                                 | 19 +++++++++++++++++++
 apps/advanced/frontend/tests/_data/dump.sql                               |  1 +
 apps/advanced/frontend/tests/_helpers/CodeHelper.php                      |  8 ++++++++
 apps/advanced/frontend/tests/_helpers/TestHelper.php                      |  8 ++++++++
 apps/advanced/frontend/tests/_helpers/WebHelper.php                       |  8 ++++++++
 apps/advanced/frontend/tests/_log/.gitignore                              |  2 ++
 apps/advanced/frontend/tests/_pages/AboutPage.php                         | 10 ++++++++++
 apps/advanced/frontend/tests/_pages/ContactPage.php                       | 22 ++++++++++++++++++++++
 apps/advanced/frontend/tests/_pages/SignupPage.php                        | 24 ++++++++++++++++++++++++
 apps/advanced/frontend/tests/acceptance.suite.yml                         | 28 ++++++++++++++++++++++++++++
 apps/advanced/frontend/tests/acceptance/AboutCept.php                     |  8 ++++++++
 apps/advanced/frontend/tests/acceptance/ContactCept.php                   | 45 +++++++++++++++++++++++++++++++++++++++++++++
 apps/advanced/frontend/tests/acceptance/HomeCept.php                      |  9 +++++++++
 apps/advanced/frontend/tests/acceptance/LoginCept.php                     | 30 ++++++++++++++++++++++++++++++
 apps/advanced/frontend/tests/acceptance/SignupCest.php                    | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 apps/advanced/frontend/tests/acceptance/_bootstrap.php                    |  3 +++
 apps/advanced/frontend/tests/acceptance/_config.php                       | 16 ++++++++++++++++
 apps/advanced/frontend/tests/acceptance/_console.php                      | 15 +++++++++++++++
 apps/advanced/frontend/tests/acceptance/yii                               | 21 +++++++++++++++++++++
 apps/advanced/frontend/tests/acceptance/yii.bat                           | 20 ++++++++++++++++++++
 apps/advanced/frontend/tests/functional.suite.yml                         | 18 ++++++++++++++++++
 apps/advanced/frontend/tests/functional/AboutCept.php                     |  8 ++++++++
 apps/advanced/frontend/tests/functional/ContactCept.php                   | 45 +++++++++++++++++++++++++++++++++++++++++++++
 apps/advanced/frontend/tests/functional/HomeCept.php                      |  9 +++++++++
 apps/advanced/frontend/tests/functional/LoginCept.php                     | 30 ++++++++++++++++++++++++++++++
 apps/advanced/frontend/tests/functional/SignupCest.php                    | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 apps/advanced/frontend/tests/functional/_bootstrap.php                    |  3 +++
 apps/advanced/frontend/tests/functional/_config.php                       | 20 ++++++++++++++++++++
 apps/advanced/frontend/tests/functional/_console.php                      | 15 +++++++++++++++
 apps/advanced/frontend/tests/functional/yii                               | 21 +++++++++++++++++++++
 apps/advanced/frontend/tests/functional/yii.bat                           | 20 ++++++++++++++++++++
 apps/advanced/frontend/tests/unit.suite.yml                               |  8 ++++++++
 apps/advanced/frontend/tests/unit/CodeGuy.php                             | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 apps/advanced/frontend/tests/unit/DbTestCase.php                          |  8 ++++++++
 apps/advanced/frontend/tests/unit/_bootstrap.php                          |  2 ++
 apps/advanced/frontend/tests/unit/_config.php                             | 16 ++++++++++++++++
 apps/advanced/frontend/tests/unit/_console.php                            | 15 +++++++++++++++
 apps/advanced/frontend/tests/unit/fixtures/data/tbl_user.php              | 23 +++++++++++++++++++++++
 apps/advanced/frontend/tests/unit/models/ContactFormTest.php              | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 apps/advanced/frontend/tests/unit/models/PasswordResetRequestFormTest.php | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 apps/advanced/frontend/tests/unit/models/ResetPasswordFormTest.php        | 37 +++++++++++++++++++++++++++++++++++++
 apps/advanced/frontend/tests/unit/models/SignupFormTest.php               | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 apps/advanced/frontend/tests/unit/yii                                     | 21 +++++++++++++++++++++
 apps/advanced/frontend/tests/unit/yii.bat                                 | 20 ++++++++++++++++++++
 47 files changed, 1090 insertions(+)
 create mode 100644 apps/advanced/frontend/codeception.yml
 create mode 100644 apps/advanced/frontend/tests/_bootstrap.php
 create mode 100644 apps/advanced/frontend/tests/_config.php
 create mode 100644 apps/advanced/frontend/tests/_console.php
 create mode 100644 apps/advanced/frontend/tests/_data/dump.sql
 create mode 100644 apps/advanced/frontend/tests/_helpers/CodeHelper.php
 create mode 100644 apps/advanced/frontend/tests/_helpers/TestHelper.php
 create mode 100644 apps/advanced/frontend/tests/_helpers/WebHelper.php
 create mode 100644 apps/advanced/frontend/tests/_log/.gitignore
 create mode 100644 apps/advanced/frontend/tests/_pages/AboutPage.php
 create mode 100644 apps/advanced/frontend/tests/_pages/ContactPage.php
 create mode 100644 apps/advanced/frontend/tests/_pages/SignupPage.php
 create mode 100644 apps/advanced/frontend/tests/acceptance.suite.yml
 create mode 100644 apps/advanced/frontend/tests/acceptance/AboutCept.php
 create mode 100644 apps/advanced/frontend/tests/acceptance/ContactCept.php
 create mode 100644 apps/advanced/frontend/tests/acceptance/HomeCept.php
 create mode 100644 apps/advanced/frontend/tests/acceptance/LoginCept.php
 create mode 100644 apps/advanced/frontend/tests/acceptance/SignupCest.php
 create mode 100644 apps/advanced/frontend/tests/acceptance/_bootstrap.php
 create mode 100644 apps/advanced/frontend/tests/acceptance/_config.php
 create mode 100644 apps/advanced/frontend/tests/acceptance/_console.php
 create mode 100644 apps/advanced/frontend/tests/acceptance/yii
 create mode 100644 apps/advanced/frontend/tests/acceptance/yii.bat
 create mode 100644 apps/advanced/frontend/tests/functional.suite.yml
 create mode 100644 apps/advanced/frontend/tests/functional/AboutCept.php
 create mode 100644 apps/advanced/frontend/tests/functional/ContactCept.php
 create mode 100644 apps/advanced/frontend/tests/functional/HomeCept.php
 create mode 100644 apps/advanced/frontend/tests/functional/LoginCept.php
 create mode 100644 apps/advanced/frontend/tests/functional/SignupCest.php
 create mode 100644 apps/advanced/frontend/tests/functional/_bootstrap.php
 create mode 100644 apps/advanced/frontend/tests/functional/_config.php
 create mode 100644 apps/advanced/frontend/tests/functional/_console.php
 create mode 100644 apps/advanced/frontend/tests/functional/yii
 create mode 100644 apps/advanced/frontend/tests/functional/yii.bat
 create mode 100644 apps/advanced/frontend/tests/unit.suite.yml
 create mode 100644 apps/advanced/frontend/tests/unit/CodeGuy.php
 create mode 100644 apps/advanced/frontend/tests/unit/DbTestCase.php
 create mode 100644 apps/advanced/frontend/tests/unit/_bootstrap.php
 create mode 100644 apps/advanced/frontend/tests/unit/_config.php
 create mode 100644 apps/advanced/frontend/tests/unit/_console.php
 create mode 100644 apps/advanced/frontend/tests/unit/fixtures/data/tbl_user.php
 create mode 100644 apps/advanced/frontend/tests/unit/models/ContactFormTest.php
 create mode 100644 apps/advanced/frontend/tests/unit/models/PasswordResetRequestFormTest.php
 create mode 100644 apps/advanced/frontend/tests/unit/models/ResetPasswordFormTest.php
 create mode 100644 apps/advanced/frontend/tests/unit/models/SignupFormTest.php
 create mode 100644 apps/advanced/frontend/tests/unit/yii
 create mode 100644 apps/advanced/frontend/tests/unit/yii.bat

diff --git a/apps/advanced/frontend/codeception.yml b/apps/advanced/frontend/codeception.yml
new file mode 100644
index 0000000..5b1f441
--- /dev/null
+++ b/apps/advanced/frontend/codeception.yml
@@ -0,0 +1,18 @@
+paths:
+    tests: tests
+    log: tests/_log
+    data: tests/_data
+    helpers: tests/_helpers
+settings:
+    bootstrap: _bootstrap.php
+    suite_class: \PHPUnit_Framework_TestSuite
+    colors: true
+    memory_limit: 1024M
+    log: true
+modules:
+    config:
+        Db:
+            dsn: ''
+            user: ''
+            password: ''
+            dump: tests/_data/dump.sql
diff --git a/apps/advanced/frontend/tests/_bootstrap.php b/apps/advanced/frontend/tests/_bootstrap.php
new file mode 100644
index 0000000..09f11dd
--- /dev/null
+++ b/apps/advanced/frontend/tests/_bootstrap.php
@@ -0,0 +1,23 @@
+<?php
+
+// the entry script URL (without host info) for functional and acceptance tests
+// PLEASE ADJUST IT TO THE ACTUAL ENTRY SCRIPT URL
+defined('TEST_ENTRY_URL') or define('TEST_ENTRY_URL', '/frontend/web/index-test.php');
+
+// the entry script file path for functional and acceptance tests
+defined('TEST_ENTRY_FILE') or define('TEST_ENTRY_FILE', dirname(__DIR__) . '/web/index-test.php');
+
+defined('YII_DEBUG') or define('YII_DEBUG', true);
+
+defined('YII_ENV') or define('YII_ENV', 'test');
+
+require_once(__DIR__ . '/../../vendor/autoload.php');
+
+require_once(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
+
+require(__DIR__ . '/../../common/config/aliases.php');
+
+// set correct script paths
+$_SERVER['SCRIPT_FILENAME'] = TEST_ENTRY_FILE;
+$_SERVER['SCRIPT_NAME'] = TEST_ENTRY_URL;
+$_SERVER['SERVER_NAME'] = 'localhost';
diff --git a/apps/advanced/frontend/tests/_config.php b/apps/advanced/frontend/tests/_config.php
new file mode 100644
index 0000000..f09e8df
--- /dev/null
+++ b/apps/advanced/frontend/tests/_config.php
@@ -0,0 +1,14 @@
+<?php
+/**
+ * application configurations shared by all test types
+ */
+return [
+	'components' => [
+		'mail' => [
+			'useFileTransport' => true,
+		],
+		'urlManager' => [
+			'showScriptName' => true,
+		],
+	],
+];
\ No newline at end of file
diff --git a/apps/advanced/frontend/tests/_console.php b/apps/advanced/frontend/tests/_console.php
new file mode 100644
index 0000000..b38c84e
--- /dev/null
+++ b/apps/advanced/frontend/tests/_console.php
@@ -0,0 +1,19 @@
+<?php
+/**
+ * Yii console bootstrap file.
+ *
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright (c) 2008 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ */
+
+// fcgi doesn't have STDIN and STDOUT defined by default
+defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
+defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w'));
+
+require_once(__DIR__ . '/../../vendor/autoload.php');
+require_once(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
+require_once(__DIR__ . '/../../common/config/aliases.php');
+
+defined('YII_DEBUG') or define('YII_DEBUG', true);
+defined('YII_ENV') or define('YII_ENV', 'test');
diff --git a/apps/advanced/frontend/tests/_data/dump.sql b/apps/advanced/frontend/tests/_data/dump.sql
new file mode 100644
index 0000000..4bc742c
--- /dev/null
+++ b/apps/advanced/frontend/tests/_data/dump.sql
@@ -0,0 +1 @@
+/* Replace this file with actual dump of your database */
\ No newline at end of file
diff --git a/apps/advanced/frontend/tests/_helpers/CodeHelper.php b/apps/advanced/frontend/tests/_helpers/CodeHelper.php
new file mode 100644
index 0000000..972c8f3
--- /dev/null
+++ b/apps/advanced/frontend/tests/_helpers/CodeHelper.php
@@ -0,0 +1,8 @@
+<?php
+namespace Codeception\Module;
+
+// here you can define custom functions for CodeGuy 
+
+class CodeHelper extends \Codeception\Module
+{
+}
diff --git a/apps/advanced/frontend/tests/_helpers/TestHelper.php b/apps/advanced/frontend/tests/_helpers/TestHelper.php
new file mode 100644
index 0000000..37737cd
--- /dev/null
+++ b/apps/advanced/frontend/tests/_helpers/TestHelper.php
@@ -0,0 +1,8 @@
+<?php
+namespace Codeception\Module;
+
+// here you can define custom functions for TestGuy 
+
+class TestHelper extends \Codeception\Module
+{
+}
diff --git a/apps/advanced/frontend/tests/_helpers/WebHelper.php b/apps/advanced/frontend/tests/_helpers/WebHelper.php
new file mode 100644
index 0000000..66b070e
--- /dev/null
+++ b/apps/advanced/frontend/tests/_helpers/WebHelper.php
@@ -0,0 +1,8 @@
+<?php
+namespace Codeception\Module;
+
+// here you can define custom functions for WebGuy 
+
+class WebHelper extends \Codeception\Module
+{
+}
diff --git a/apps/advanced/frontend/tests/_log/.gitignore b/apps/advanced/frontend/tests/_log/.gitignore
new file mode 100644
index 0000000..d6b7ef3
--- /dev/null
+++ b/apps/advanced/frontend/tests/_log/.gitignore
@@ -0,0 +1,2 @@
+*
+!.gitignore
diff --git a/apps/advanced/frontend/tests/_pages/AboutPage.php b/apps/advanced/frontend/tests/_pages/AboutPage.php
new file mode 100644
index 0000000..8ad0134
--- /dev/null
+++ b/apps/advanced/frontend/tests/_pages/AboutPage.php
@@ -0,0 +1,10 @@
+<?php
+
+namespace frontend\tests\_pages;
+
+use yii\codeception\BasePage;
+
+class AboutPage extends BasePage
+{
+	public $route = 'site/about';
+}
diff --git a/apps/advanced/frontend/tests/_pages/ContactPage.php b/apps/advanced/frontend/tests/_pages/ContactPage.php
new file mode 100644
index 0000000..cb5cb6c
--- /dev/null
+++ b/apps/advanced/frontend/tests/_pages/ContactPage.php
@@ -0,0 +1,22 @@
+<?php
+
+namespace frontend\tests\_pages;
+
+use yii\codeception\BasePage;
+
+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->guy->fillField($inputType . '[name="ContactForm[' . $field . ']"]', $value);
+		}
+		$this->guy->click('contact-button');
+	}
+}
\ No newline at end of file
diff --git a/apps/advanced/frontend/tests/_pages/SignupPage.php b/apps/advanced/frontend/tests/_pages/SignupPage.php
new file mode 100644
index 0000000..1c7ff1b
--- /dev/null
+++ b/apps/advanced/frontend/tests/_pages/SignupPage.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace frontend\tests\_pages;
+
+use \yii\codeception\BasePage;
+
+class SignupPage extends BasePage
+{
+
+	public $route = 'site/signup';
+
+	/**
+	 * @param array $signupData
+	 */
+	public function submit(array $signupData)
+	{
+		foreach ($signupData as $field => $value) {
+			$inputType = $field === 'body' ? 'textarea' : 'input';
+			$this->guy->fillField($inputType . '[name="SignupForm[' . $field . ']"]', $value);
+		}
+		$this->guy->click('signup-button');
+	}
+
+}
\ No newline at end of file
diff --git a/apps/advanced/frontend/tests/acceptance.suite.yml b/apps/advanced/frontend/tests/acceptance.suite.yml
new file mode 100644
index 0000000..5a9916a
--- /dev/null
+++ b/apps/advanced/frontend/tests/acceptance.suite.yml
@@ -0,0 +1,28 @@
+# 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: WebGuy
+modules:
+    enabled:
+        - WebHelper
+        - PhpBrowser
+        - common\tests\_helpers\FixtureHelper
+# you can use WebDriver instead of PhpBrowser to test javascript and ajax.
+# This will require you to install selenium. See http://codeception.com/docs/04-AcceptanceTests#Selenium
+# "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:
+            url: 'http://localhost:8080'
+#        WebDriver:
+#            url: 'http://localhost'
+#            browser: firefox
+#            restart: true
\ No newline at end of file
diff --git a/apps/advanced/frontend/tests/acceptance/AboutCept.php b/apps/advanced/frontend/tests/acceptance/AboutCept.php
new file mode 100644
index 0000000..71e387c
--- /dev/null
+++ b/apps/advanced/frontend/tests/acceptance/AboutCept.php
@@ -0,0 +1,8 @@
+<?php
+
+use frontend\tests\_pages\AboutPage;
+
+$I = new WebGuy($scenario);
+$I->wantTo('ensure that about works');
+AboutPage::openBy($I);
+$I->see('About', 'h1');
diff --git a/apps/advanced/frontend/tests/acceptance/ContactCept.php b/apps/advanced/frontend/tests/acceptance/ContactCept.php
new file mode 100644
index 0000000..84c2911
--- /dev/null
+++ b/apps/advanced/frontend/tests/acceptance/ContactCept.php
@@ -0,0 +1,45 @@
+<?php
+
+use frontend\tests\_pages\ContactPage;
+
+$I = new WebGuy($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 adress 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->see('Thank you for contacting us. We will respond to you as soon as possible.');
diff --git a/apps/advanced/frontend/tests/acceptance/HomeCept.php b/apps/advanced/frontend/tests/acceptance/HomeCept.php
new file mode 100644
index 0000000..62456f9
--- /dev/null
+++ b/apps/advanced/frontend/tests/acceptance/HomeCept.php
@@ -0,0 +1,9 @@
+<?php
+
+$I = new WebGuy($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.');
diff --git a/apps/advanced/frontend/tests/acceptance/LoginCept.php b/apps/advanced/frontend/tests/acceptance/LoginCept.php
new file mode 100644
index 0000000..55eed40
--- /dev/null
+++ b/apps/advanced/frontend/tests/acceptance/LoginCept.php
@@ -0,0 +1,30 @@
+<?php
+
+use common\tests\_pages\LoginPage;
+
+$I = new WebGuy($scenario);
+$I->wantTo('ensure login page works');
+
+$loginPage = LoginPage::openBy($I);
+
+$I->amGoingTo('submit login form with no data');
+$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');
+$I->expectTo('see validations errors');
+$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('erau', 'password_0');
+$I->expectTo('see that user is logged');
+$I->see('Logout (erau)');
+$I->dontSee('Login');
+$I->dontSee('Signup');
+$I->click('Logout (erau)');
+$I->dontSee('Logout (erau)');
+$I->see('Login');
\ No newline at end of file
diff --git a/apps/advanced/frontend/tests/acceptance/SignupCest.php b/apps/advanced/frontend/tests/acceptance/SignupCest.php
new file mode 100644
index 0000000..a166f34
--- /dev/null
+++ b/apps/advanced/frontend/tests/acceptance/SignupCest.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace frontend\tests\acceptance;
+
+use frontend\tests\_pages\SignupPage;
+use common\models\User;
+
+class SignupCest
+{
+
+	/**
+	 * This method is called after each cest class test method
+	 * @param \Codeception\Event\Test $event
+	 */
+	public function _before($event)
+	{
+	}
+
+	/**
+	 * This method is called after each cest class test method, even if test failed.
+	 * @param \Codeception\Event\Test $event
+	 */
+	public function _after($event)
+	{
+		User::deleteAll([
+			'email' => 'tester.email@example.com',
+			'username' => 'tester',
+		]);
+	}
+
+	/**
+	 * This method is called when test fails.
+	 * @param \Codeception\Event\Fail $event
+	 */
+	public function _fail($event)
+	{
+	}
+
+	/**
+	 * 
+	 * @param \WebGuy $I
+	 * @param \Codeception\Scenario $scenario
+	 */
+	public function testUserSignup($I, $scenario)
+	{
+		$I->wantTo('ensure that signup works');
+
+		$signupPage = SignupPage::openBy($I);
+		$I->see('Please fill out the following fields to signup:');
+
+		$I->amGoingTo('submit signup form with no data');
+
+		$signupPage->submit([]);
+
+		$I->expectTo('see validation errors');
+		$I->see('Username cannot be blank.');
+		$I->see('Email cannot be blank.');
+		$I->see('Password cannot be blank.');
+
+		$I->amGoingTo('submit signup form with not correct email');
+		$signupPage->submit([
+			'username'		=>	'tester',
+			'email'			=>	'tester.email',
+			'password'		=>	'tester_password',
+		]);
+
+		$I->expectTo('see that email adress is wrong');
+		$I->dontSee('Username cannot be blank.', '.help-inline');
+		$I->dontSee('Password cannot be blank.', '.help-inline');
+		$I->see('Email is not a valid email address.', '.help-block');
+
+		$I->amGoingTo('submit signup form with correct email');
+		$signupPage->submit([
+			'username'		=>	'tester',
+			'email'			=>	'tester.email@example.com',
+			'password'		=>	'tester_password',
+		]);
+
+		$I->expectTo('see that user logged in');
+		$I->see('Logout (tester)');
+	}
+
+}
diff --git a/apps/advanced/frontend/tests/acceptance/_bootstrap.php b/apps/advanced/frontend/tests/acceptance/_bootstrap.php
new file mode 100644
index 0000000..6ce3d17
--- /dev/null
+++ b/apps/advanced/frontend/tests/acceptance/_bootstrap.php
@@ -0,0 +1,3 @@
+<?php
+
+new yii\web\Application(require(__DIR__ . '/_config.php'));
diff --git a/apps/advanced/frontend/tests/acceptance/_config.php b/apps/advanced/frontend/tests/acceptance/_config.php
new file mode 100644
index 0000000..82cb2f5
--- /dev/null
+++ b/apps/advanced/frontend/tests/acceptance/_config.php
@@ -0,0 +1,16 @@
+<?php
+
+return yii\helpers\ArrayHelper::merge(
+	require(__DIR__ . '/../../config/main.php'),
+	require(__DIR__ . '/../../config/main-local.php'),
+	require(__DIR__ . '/../../../common/config/main.php'),
+	require(__DIR__ . '/../../../common/config/main-local.php'),
+	require(__DIR__ . '/../_config.php'),
+	[
+		'components' => [
+			'db' => [
+				'dsn' => 'pgsql:host=localhost;dbname=yii2_advanced_acceptance',
+			],
+		],
+	]
+);
diff --git a/apps/advanced/frontend/tests/acceptance/_console.php b/apps/advanced/frontend/tests/acceptance/_console.php
new file mode 100644
index 0000000..1ae9bc4
--- /dev/null
+++ b/apps/advanced/frontend/tests/acceptance/_console.php
@@ -0,0 +1,15 @@
+<?php
+
+return yii\helpers\ArrayHelper::merge(
+	require(__DIR__ . '/../../../common/config/main.php'),
+	require(__DIR__ . '/../../../common/config/main-local.php'),
+	require(__DIR__ . '/../../../console/config/main.php'),
+	require(__DIR__ . '/../../../console/config/main-local.php'),
+	[
+		'components' => [
+			'db' => [
+				'dsn' => 'pgsql:host=localhost;dbname=yii2_advanced_acceptance',
+			],
+		],
+	]
+);
diff --git a/apps/advanced/frontend/tests/acceptance/yii b/apps/advanced/frontend/tests/acceptance/yii
new file mode 100644
index 0000000..a348a9a
--- /dev/null
+++ b/apps/advanced/frontend/tests/acceptance/yii
@@ -0,0 +1,21 @@
+#!/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/
+ */
+
+// fcgi doesn't have STDIN and STDOUT defined by default
+defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
+defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w'));
+
+require_once(__DIR__ . '/../_console.php');
+
+$config = require(__DIR__ . '/_console.php');
+
+$application = new yii\console\Application($config);
+$exitCode = $application->run();
+exit($exitCode);
diff --git a/apps/advanced/frontend/tests/acceptance/yii.bat b/apps/advanced/frontend/tests/acceptance/yii.bat
new file mode 100644
index 0000000..5e21e2e
--- /dev/null
+++ b/apps/advanced/frontend/tests/acceptance/yii.bat
@@ -0,0 +1,20 @@
+@echo off
+
+rem -------------------------------------------------------------
+rem  Yii command line bootstrap script for Windows.
+rem
+rem  @author Qiang Xue <qiang.xue@gmail.com>
+rem  @link http://www.yiiframework.com/
+rem  @copyright Copyright &copy; 2012 Yii Software LLC
+rem  @license http://www.yiiframework.com/license/
+rem -------------------------------------------------------------
+
+@setlocal
+
+set YII_PATH=%~dp0
+
+if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe
+
+"%PHP_COMMAND%" "%YII_PATH%yii" %*
+
+@endlocal
diff --git a/apps/advanced/frontend/tests/functional.suite.yml b/apps/advanced/frontend/tests/functional.suite.yml
new file mode 100644
index 0000000..3113794
--- /dev/null
+++ b/apps/advanced/frontend/tests/functional.suite.yml
@@ -0,0 +1,18 @@
+# Codeception Test Suite Configuration
+
+# suite for functional (integration) tests.
+# emulate web requests and make application process them.
+# (tip: better to use with frameworks).
+
+# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.
+#basic/web/index.php
+class_name: TestGuy
+modules:
+    enabled:
+      - Filesystem
+      - TestHelper
+      - Yii2
+      - common\tests\_helpers\FixtureHelper
+    config:
+        Yii2:
+            configFile: 'tests/functional/_config.php'
\ No newline at end of file
diff --git a/apps/advanced/frontend/tests/functional/AboutCept.php b/apps/advanced/frontend/tests/functional/AboutCept.php
new file mode 100644
index 0000000..b2153b3
--- /dev/null
+++ b/apps/advanced/frontend/tests/functional/AboutCept.php
@@ -0,0 +1,8 @@
+<?php
+
+use frontend\tests\_pages\AboutPage;
+
+$I = new TestGuy($scenario);
+$I->wantTo('ensure that about works');
+AboutPage::openBy($I);
+$I->see('About', 'h1');
diff --git a/apps/advanced/frontend/tests/functional/ContactCept.php b/apps/advanced/frontend/tests/functional/ContactCept.php
new file mode 100644
index 0000000..7fc1ddb
--- /dev/null
+++ b/apps/advanced/frontend/tests/functional/ContactCept.php
@@ -0,0 +1,45 @@
+<?php
+
+use frontend\tests\_pages\ContactPage;
+
+$I = new TestGuy($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 adress 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->see('Thank you for contacting us. We will respond to you as soon as possible.');
diff --git a/apps/advanced/frontend/tests/functional/HomeCept.php b/apps/advanced/frontend/tests/functional/HomeCept.php
new file mode 100644
index 0000000..3258ba3
--- /dev/null
+++ b/apps/advanced/frontend/tests/functional/HomeCept.php
@@ -0,0 +1,9 @@
+<?php
+
+$I = new TestGuy($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.');
diff --git a/apps/advanced/frontend/tests/functional/LoginCept.php b/apps/advanced/frontend/tests/functional/LoginCept.php
new file mode 100644
index 0000000..1d2dc14
--- /dev/null
+++ b/apps/advanced/frontend/tests/functional/LoginCept.php
@@ -0,0 +1,30 @@
+<?php
+
+use common\tests\_pages\LoginPage;
+
+$I = new TestGuy($scenario);
+$I->wantTo('ensure login page works');
+
+$loginPage = LoginPage::openBy($I);
+
+$I->amGoingTo('submit login form with no data');
+$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');
+$I->expectTo('see validations errors');
+$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('erau', 'password_0');
+$I->expectTo('see that user is logged');
+$I->see('Logout (erau)');
+$I->dontSee('Login');
+$I->dontSee('Signup');
+$I->click('Logout (erau)');
+$I->dontSee('Logout (erau)');
+$I->see('Login');
diff --git a/apps/advanced/frontend/tests/functional/SignupCest.php b/apps/advanced/frontend/tests/functional/SignupCest.php
new file mode 100644
index 0000000..cfef787
--- /dev/null
+++ b/apps/advanced/frontend/tests/functional/SignupCest.php
@@ -0,0 +1,83 @@
+<?php
+
+namespace frontend\tests\functional;
+
+use frontend\tests\_pages\SignupPage;
+use common\models\User;
+
+class SignupCest
+{
+
+	/**
+	 * This method is called after each cest class test method
+	 * @param \Codeception\Event\Test $event
+	 */
+	public function _before($event)
+	{
+	}
+
+	/**
+	 * This method is called after each cest class test method, even if test failed.
+	 * @param \Codeception\Event\Test $event
+	 */
+	public function _after($event)
+	{
+		User::deleteAll([
+			'email' => 'tester.email@example.com',
+			'username' => 'tester',
+		]);
+	}
+
+	/**
+	 * This method is called when test fails.
+	 * @param \Codeception\Event\Fail $event
+	 */
+	public function _fail($event)
+	{
+	}
+
+	/**
+	 * 
+	 * @param \TestGuy $I
+	 * @param \Codeception\Scenario $scenario
+	 */
+	public function testUserSignup($I, $scenario)
+	{
+		$I->wantTo('ensure that signup works');
+
+		$signupPage = SignupPage::openBy($I);
+		$I->see('Please fill out the following fields to signup:');
+
+		$I->amGoingTo('submit signup form with no data');
+
+		$signupPage->submit([]);
+
+		$I->expectTo('see validation errors');
+		$I->see('Username cannot be blank.');
+		$I->see('Email cannot be blank.');
+		$I->see('Password cannot be blank.');
+
+		$I->amGoingTo('submit signup form with not correct email');
+		$signupPage->submit([
+			'username'		=>	'tester',
+			'email'			=>	'tester.email',
+			'password'		=>	'tester_password',
+		]);
+
+		$I->expectTo('see that email adress is wrong');
+		$I->dontSee('Username cannot be blank.', '.help-inline');
+		$I->dontSee('Password cannot be blank.', '.help-inline');
+		$I->see('Email is not a valid email address.', '.help-block');
+
+		$I->amGoingTo('submit signup form with correct email');
+		$signupPage->submit([
+			'username'		=>	'tester',
+			'email'			=>	'tester.email@example.com',
+			'password'		=>	'tester_password',
+		]);
+
+		$I->expectTo('see that user logged in');
+		$I->see('Logout (tester)');
+	}
+
+}
diff --git a/apps/advanced/frontend/tests/functional/_bootstrap.php b/apps/advanced/frontend/tests/functional/_bootstrap.php
new file mode 100644
index 0000000..6ce3d17
--- /dev/null
+++ b/apps/advanced/frontend/tests/functional/_bootstrap.php
@@ -0,0 +1,3 @@
+<?php
+
+new yii\web\Application(require(__DIR__ . '/_config.php'));
diff --git a/apps/advanced/frontend/tests/functional/_config.php b/apps/advanced/frontend/tests/functional/_config.php
new file mode 100644
index 0000000..fb19bad
--- /dev/null
+++ b/apps/advanced/frontend/tests/functional/_config.php
@@ -0,0 +1,20 @@
+<?php
+
+// set correct script paths
+$_SERVER['SCRIPT_FILENAME'] = TEST_ENTRY_FILE;
+$_SERVER['SCRIPT_NAME'] = TEST_ENTRY_URL;
+
+return yii\helpers\ArrayHelper::merge(
+	require(__DIR__ . '/../../config/main.php'),
+	require(__DIR__ . '/../../config/main-local.php'),
+	require(__DIR__ . '/../../../common/config/main.php'),
+	require(__DIR__ . '/../../../common/config/main-local.php'),
+	require(__DIR__ . '/../_config.php'),
+	[
+		'components' => [
+			'db' => [
+				'dsn' => 'pgsql:host=localhost;dbname=yii2_advanced_functional',
+			],
+		],
+	]
+);
diff --git a/apps/advanced/frontend/tests/functional/_console.php b/apps/advanced/frontend/tests/functional/_console.php
new file mode 100644
index 0000000..13dc3d2
--- /dev/null
+++ b/apps/advanced/frontend/tests/functional/_console.php
@@ -0,0 +1,15 @@
+<?php
+
+return yii\helpers\ArrayHelper::merge(
+	require(__DIR__ . '/../../../common/config/main.php'),
+	require(__DIR__ . '/../../../common/config/main-local.php'),
+	require(__DIR__ . '/../../../console/config/main.php'),
+	require(__DIR__ . '/../../../console/config/main-local.php'),
+	[
+		'components' => [
+			'db' => [
+				'dsn' => 'pgsql:host=localhost;dbname=yii2_advanced_functional',
+			],
+		],
+	]
+);
diff --git a/apps/advanced/frontend/tests/functional/yii b/apps/advanced/frontend/tests/functional/yii
new file mode 100644
index 0000000..a348a9a
--- /dev/null
+++ b/apps/advanced/frontend/tests/functional/yii
@@ -0,0 +1,21 @@
+#!/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/
+ */
+
+// fcgi doesn't have STDIN and STDOUT defined by default
+defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
+defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w'));
+
+require_once(__DIR__ . '/../_console.php');
+
+$config = require(__DIR__ . '/_console.php');
+
+$application = new yii\console\Application($config);
+$exitCode = $application->run();
+exit($exitCode);
diff --git a/apps/advanced/frontend/tests/functional/yii.bat b/apps/advanced/frontend/tests/functional/yii.bat
new file mode 100644
index 0000000..5e21e2e
--- /dev/null
+++ b/apps/advanced/frontend/tests/functional/yii.bat
@@ -0,0 +1,20 @@
+@echo off
+
+rem -------------------------------------------------------------
+rem  Yii command line bootstrap script for Windows.
+rem
+rem  @author Qiang Xue <qiang.xue@gmail.com>
+rem  @link http://www.yiiframework.com/
+rem  @copyright Copyright &copy; 2012 Yii Software LLC
+rem  @license http://www.yiiframework.com/license/
+rem -------------------------------------------------------------
+
+@setlocal
+
+set YII_PATH=%~dp0
+
+if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe
+
+"%PHP_COMMAND%" "%YII_PATH%yii" %*
+
+@endlocal
diff --git a/apps/advanced/frontend/tests/unit.suite.yml b/apps/advanced/frontend/tests/unit.suite.yml
new file mode 100644
index 0000000..04873a8
--- /dev/null
+++ b/apps/advanced/frontend/tests/unit.suite.yml
@@ -0,0 +1,8 @@
+# Codeception Test Suite Configuration
+
+# suite for unit (internal) tests.
+# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.
+
+class_name: CodeGuy
+modules:
+    enabled: [CodeHelper]
diff --git a/apps/advanced/frontend/tests/unit/CodeGuy.php b/apps/advanced/frontend/tests/unit/CodeGuy.php
new file mode 100644
index 0000000..9dd19de
--- /dev/null
+++ b/apps/advanced/frontend/tests/unit/CodeGuy.php
@@ -0,0 +1,47 @@
+<?php
+// This class was automatically generated by build task
+// You should not change it manually as it will be overwritten on next build
+// @codingStandardsIgnoreFile
+
+
+use \Codeception\Maybe;
+use Codeception\Module\CodeHelper;
+
+/**
+ * Inherited methods
+ * @method void execute($callable)
+ * @method void wantToTest($text)
+ * @method void wantTo($text)
+ * @method void expectTo($prediction)
+ * @method void expect($prediction)
+ * @method void amGoingTo($argumentation)
+ * @method void am($role)
+ * @method void lookForwardTo($achieveValue)
+ * @method void offsetGet($offset)
+ * @method void offsetSet($offset, $value)
+ * @method void offsetExists($offset)
+ * @method void offsetUnset($offset)
+*/
+
+class CodeGuy extends \Codeception\AbstractGuy
+{
+    
+    /**
+     * This method is generated.
+     * Documentation taken from corresponding module.
+     * ----------------------------------------------
+     *
+     *
+     * @see Codeception\Module::getName()
+     * @return \Codeception\Maybe
+     */
+    public function getName() {
+        $this->scenario->addStep(new \Codeception\Step\Action('getName', func_get_args()));
+        if ($this->scenario->running()) {
+            $result = $this->scenario->runStep();
+            return new Maybe($result);
+        }
+        return new Maybe();
+    }
+}
+
diff --git a/apps/advanced/frontend/tests/unit/DbTestCase.php b/apps/advanced/frontend/tests/unit/DbTestCase.php
new file mode 100644
index 0000000..998d5b8
--- /dev/null
+++ b/apps/advanced/frontend/tests/unit/DbTestCase.php
@@ -0,0 +1,8 @@
+<?php
+
+namespace frontend\tests\unit;
+
+class DbTestCase extends \yii\codeception\DbTestCase
+{
+	public $appConfig = '@frontend/tests/unit/_config.php';
+}
diff --git a/apps/advanced/frontend/tests/unit/_bootstrap.php b/apps/advanced/frontend/tests/unit/_bootstrap.php
new file mode 100644
index 0000000..db5706d
--- /dev/null
+++ b/apps/advanced/frontend/tests/unit/_bootstrap.php
@@ -0,0 +1,2 @@
+<?php
+// Here you can initialize variables that will for your tests
\ No newline at end of file
diff --git a/apps/advanced/frontend/tests/unit/_config.php b/apps/advanced/frontend/tests/unit/_config.php
new file mode 100644
index 0000000..79842a6
--- /dev/null
+++ b/apps/advanced/frontend/tests/unit/_config.php
@@ -0,0 +1,16 @@
+<?php
+
+return yii\helpers\ArrayHelper::merge(
+	require(__DIR__ . '/../../../common/config/main.php'),
+	require(__DIR__ . '/../../../common/config/main-local.php'),
+	require(__DIR__ . '/../../config/main.php'),
+	require(__DIR__ . '/../../config/main-local.php'),
+	require(__DIR__ . '/../_config.php'),
+	[
+		'components' => [
+			'db' => [
+				'dsn' => 'pgsql:host=localhost;dbname=yii2_advanced_unit',
+			],
+		],
+	]
+);
diff --git a/apps/advanced/frontend/tests/unit/_console.php b/apps/advanced/frontend/tests/unit/_console.php
new file mode 100644
index 0000000..9f3d75c
--- /dev/null
+++ b/apps/advanced/frontend/tests/unit/_console.php
@@ -0,0 +1,15 @@
+<?php
+
+return yii\helpers\ArrayHelper::merge(
+	require(__DIR__ . '/../../../common/config/main.php'),
+	require(__DIR__ . '/../../../common/config/main-local.php'),
+	require(__DIR__ . '/../../../console/config/main.php'),
+	require(__DIR__ . '/../../../console/config/main-local.php'),
+	[
+		'components' => [
+			'db' => [
+				'dsn' => 'pgsql:host=localhost;dbname=yii2_advanced_unit',
+			],
+		],
+	]
+);
diff --git a/apps/advanced/frontend/tests/unit/fixtures/data/tbl_user.php b/apps/advanced/frontend/tests/unit/fixtures/data/tbl_user.php
new file mode 100644
index 0000000..69552c2
--- /dev/null
+++ b/apps/advanced/frontend/tests/unit/fixtures/data/tbl_user.php
@@ -0,0 +1,23 @@
+<?php
+
+return [
+	[
+		'username' => 'okirlin',
+		'auth_key' => 'iwTNae9t34OmnK6l4vT4IeaTk-YWI2Rv',
+		'password_hash' => '$2y$13$CXT0Rkle1EMJ/c1l5bylL.EylfmQ39O5JlHJVFpNn618OUS1HwaIi',
+		'password_reset_token' => 't5GU9NwpuGYSfb7FEZMAxqtuz2PkEvv_1391885313',
+		'created_at' => '1391885313',
+		'updated_at' => '1391885313',
+		'email' => 'brady.renner@rutherford.com',
+	],
+	[
+		'username' => 'troy.becker',
+		'auth_key' => 'EdKfXrx88weFMV0vIxuTMWKgfK2tS3Lp',
+		'password_hash' => '$2y$13$g5nv41Px7VBqhS3hVsVN2.MKfgT3jFdkXEsMC4rQJLfaMa7VaJqL2',
+		'password_reset_token' => '4BSNyiZNAuxjs5Mty990c47sVrgllIi_1391885313',
+		'created_at' => '1391885313',
+		'updated_at' => '1391885313',
+		'email' => 'nicolas.dianna@hotmail.com',
+		'status' => '0',
+	],
+];
diff --git a/apps/advanced/frontend/tests/unit/models/ContactFormTest.php b/apps/advanced/frontend/tests/unit/models/ContactFormTest.php
new file mode 100644
index 0000000..23e6288
--- /dev/null
+++ b/apps/advanced/frontend/tests/unit/models/ContactFormTest.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace frontend\tests\unit\models;
+
+use Yii;
+use frontend\tests\unit\TestCase;
+
+class ContactFormTest extends TestCase
+{
+
+	use \Codeception\Specify;
+
+	protected function setUp()
+	{
+		parent::setUp();
+		Yii::$app->mail->fileTransportCallback = function ($mailer, $message) {
+			return 'testing_message.eml';
+		};
+	}
+
+	protected function tearDown()
+	{
+		unlink($this->getMessageFile());
+		parent::tearDown();
+	}
+
+	public function testContact()
+	{
+		$model = $this->getMock('frontend\models\ContactForm', ['validate']);
+		$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',
+		];
+
+		$model->contact('admin@example.com');
+
+		$this->specify('email should be send', function () {
+			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->mail->fileTransportPath) . '/testing_message.eml';
+	}
+
+}
diff --git a/apps/advanced/frontend/tests/unit/models/PasswordResetRequestFormTest.php b/apps/advanced/frontend/tests/unit/models/PasswordResetRequestFormTest.php
new file mode 100644
index 0000000..b736039
--- /dev/null
+++ b/apps/advanced/frontend/tests/unit/models/PasswordResetRequestFormTest.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace frontend\tests\unit\models;
+
+use Yii;
+use frontend\tests\unit\DbTestCase;
+use frontend\models\PasswordResetRequestForm;
+use common\tests\fixtures\UserFixture;
+use common\models\User;
+
+class PasswordResetRequestFormTest extends DbTestCase
+{
+	use \Codeception\Specify;
+
+	protected function setUp()
+	{
+		parent::setUp();
+		Yii::$app->mail->fileTransportCallback = function ($mailer, $message) {
+			return 'testing_message.eml';
+		};
+	}
+
+	protected function tearDown()
+	{
+		@unlink($this->getMessageFile());
+		parent::tearDown();
+	}
+
+	public function testSendEmailWrongUser()
+	{
+		$this->specify('no user with such email, message should not be send', function() {
+			$model = new PasswordResetRequestForm();
+			$model->email = 'not-existing-email@example.com';
+			
+			expect('email not send', $model->sendEmail())->false();
+		});
+
+		$this->specify('user is not active, message should not be send', function() {
+			$model = new PasswordResetRequestForm();
+			$model->email = $this->user[1]['email'];
+			
+			expect('email not send', $model->sendEmail())->false();
+		});
+	}
+	
+	public function testSendEmailCorrectUser()
+	{
+		$model = new PasswordResetRequestForm();
+		$model->email = $this->user[0]['email'];
+		$user = User::find(['password_reset_token' => $this->user[0]['password_reset_token']]);
+
+		expect('email sent', $model->sendEmail())->true();
+		expect('user has valid token', $user->password_reset_token)->notNull();
+			
+		$this->specify('message has correct format', function() use ($model) {
+			expect('message file exists',  file_exists($this->getMessageFile()))->true();
+
+			$message = file_get_contents($this->getMessageFile());
+			expect('message "from" is correct', $message)->contains(Yii::$app->params['supportEmail']);
+			expect('message "to" is correct', $message)->contains($model->email);
+		});
+	}
+
+	public function fixtures()
+	{
+		return [
+			'user' => [
+				'class' => UserFixture::className(),
+				'dataFile' => '@frontend/tests/unit/fixtures/data/tbl_user.php'
+			],
+		];
+	}
+
+	private function getMessageFile()
+	{
+		return Yii::getAlias(Yii::$app->mail->fileTransportPath) . '/testing_message.eml';
+	}
+
+}
diff --git a/apps/advanced/frontend/tests/unit/models/ResetPasswordFormTest.php b/apps/advanced/frontend/tests/unit/models/ResetPasswordFormTest.php
new file mode 100644
index 0000000..763683f
--- /dev/null
+++ b/apps/advanced/frontend/tests/unit/models/ResetPasswordFormTest.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace frontend\tests\unit\models;
+
+use frontend\tests\unit\DbTestCase;
+use common\tests\fixtures\UserFixture;
+use frontend\models\ResetPasswordForm;
+
+class ResetPasswordFormTest extends DbTestCase
+{
+
+	use \Codeception\Specify;
+
+	public function testResetPassword()
+	{
+		$this->specify('wrong reset token', function() {
+			$this->setExpectedException('\Exception','Wrong password reset token.');
+			new ResetPasswordForm('notexistingtoken_1391882543');
+		});
+
+		$this->specify('not correct token', function() {
+			$this->setExpectedException('yii\base\InvalidParamException','Password reset token cannot be blank.');
+			new ResetPasswordForm('');
+		});
+	}
+
+	public function fixtures()
+	{
+		return [
+			'user' => [
+				'class' => UserFixture::className(),
+				'dataFile' => '@frontend/tests/unit/fixtures/data/tbl_user.php'
+			],
+		];
+	}
+
+}
diff --git a/apps/advanced/frontend/tests/unit/models/SignupFormTest.php b/apps/advanced/frontend/tests/unit/models/SignupFormTest.php
new file mode 100644
index 0000000..5a3e8e8
--- /dev/null
+++ b/apps/advanced/frontend/tests/unit/models/SignupFormTest.php
@@ -0,0 +1,47 @@
+<?php
+
+namespace frontend\tests\unit\models;
+
+use frontend\tests\unit\DbTestCase;
+use common\tests\fixtures\UserFixture;
+
+class SingupFormTest extends DbTestCase
+{
+
+	use \Codeception\Specify;
+
+	public function testCorrectSignup()
+	{
+		$model = $this->getMock('frontend\models\SignupForm',['validate']);
+		$model->expects($this->once())->method('validate')->will($this->returnValue(true));
+
+		$model->username = 'some_username';
+		$model->email = 'some_email@example.com';
+		$model->password = 'some_password';
+
+		$user = $model->signup();
+		$this->assertInstanceOf('common\models\User', $user);
+		expect('username should be correct', $user->username)->equals('some_username');
+		expect('email should be correct', $user->email)->equals('some_email@example.com');
+		expect('password should be correct', $user->validatePassword('some_password'))->true();
+	}
+
+	public function testNotCorrectSignup()
+	{
+		$model = $this->getMock('frontend\models\SignupForm',['validate']);
+		$model->expects($this->once())->method('validate')->will($this->returnValue(false));
+
+		expect('user should not be created', $model->signup())->null();
+	}
+
+	public function fixtures()
+	{
+		return [
+			'user' => [
+				'class' => UserFixture::className(),
+				'dataFile' => false, //do not load test data, only table cleanup
+			],
+		];
+	}
+
+}
diff --git a/apps/advanced/frontend/tests/unit/yii b/apps/advanced/frontend/tests/unit/yii
new file mode 100644
index 0000000..a348a9a
--- /dev/null
+++ b/apps/advanced/frontend/tests/unit/yii
@@ -0,0 +1,21 @@
+#!/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/
+ */
+
+// fcgi doesn't have STDIN and STDOUT defined by default
+defined('STDIN') or define('STDIN', fopen('php://stdin', 'r'));
+defined('STDOUT') or define('STDOUT', fopen('php://stdout', 'w'));
+
+require_once(__DIR__ . '/../_console.php');
+
+$config = require(__DIR__ . '/_console.php');
+
+$application = new yii\console\Application($config);
+$exitCode = $application->run();
+exit($exitCode);
diff --git a/apps/advanced/frontend/tests/unit/yii.bat b/apps/advanced/frontend/tests/unit/yii.bat
new file mode 100644
index 0000000..5e21e2e
--- /dev/null
+++ b/apps/advanced/frontend/tests/unit/yii.bat
@@ -0,0 +1,20 @@
+@echo off
+
+rem -------------------------------------------------------------
+rem  Yii command line bootstrap script for Windows.
+rem
+rem  @author Qiang Xue <qiang.xue@gmail.com>
+rem  @link http://www.yiiframework.com/
+rem  @copyright Copyright &copy; 2012 Yii Software LLC
+rem  @license http://www.yiiframework.com/license/
+rem -------------------------------------------------------------
+
+@setlocal
+
+set YII_PATH=%~dp0
+
+if "%PHP_COMMAND%" == "" set PHP_COMMAND=php.exe
+
+"%PHP_COMMAND%" "%YII_PATH%yii" %*
+
+@endlocal
--
libgit2 0.27.1