Инициализировано Yii2 приложение, выпилены лишние части, накинуты чуточку нужных

This commit is contained in:
ErickSkrauch 2016-01-02 16:43:18 +03:00
commit 841303b8ab
134 changed files with 3394 additions and 0 deletions

3
.bowerrc Normal file
View File

@ -0,0 +1,3 @@
{
"directory" : "vendor/bower"
}

31
.gitignore vendored Normal file
View File

@ -0,0 +1,31 @@
# yii console command
/yii
# phpstorm project files
.idea
# netbeans project files
nbproject
# zend studio for eclipse project files
.buildpath
.project
.settings
# windows thumbnail cache
Thumbs.db
# composer vendor dir
/vendor
# composer itself is not needed
composer.phar
composer.lock
# Mac DS_Store Files
.DS_Store
# phpunit itself is not needed
phpunit.phar
# local phpunit config
/phpunit.xml

54
README.md Normal file
View File

@ -0,0 +1,54 @@
Yii 2 Advanced Project Template
===============================
Yii 2 Advanced Project Template is a skeleton [Yii 2](http://www.yiiframework.com/) application best for
developing complex Web applications with multiple tiers.
The template includes three tiers: front end, back end, and console, each of which
is a separate Yii application.
The template is designed to work in a team development environment. It supports
deploying the application in different environments.
Documentation is at [docs/guide/README.md](docs/guide/README.md).
[![Latest Stable Version](https://poser.pugx.org/yiisoft/yii2-app-advanced/v/stable.png)](https://packagist.org/packages/yiisoft/yii2-app-advanced)
[![Total Downloads](https://poser.pugx.org/yiisoft/yii2-app-advanced/downloads.png)](https://packagist.org/packages/yiisoft/yii2-app-advanced)
[![Build Status](https://travis-ci.org/yiisoft/yii2-app-advanced.svg?branch=master)](https://travis-ci.org/yiisoft/yii2-app-advanced)
DIRECTORY STRUCTURE
-------------------
```
common
config/ contains shared configurations
mail/ contains view files for e-mails
models/ contains model classes used in both backend and frontend
console
config/ contains console configurations
controllers/ contains console controllers (commands)
migrations/ contains database migrations
models/ contains console-specific model classes
runtime/ contains files generated during runtime
backend
assets/ contains application assets such as JavaScript and CSS
config/ contains backend configurations
controllers/ contains Web controller classes
models/ contains backend-specific model classes
runtime/ contains files generated during runtime
views/ contains view files for the Web application
web/ contains the entry script and Web resources
frontend
assets/ contains application assets such as JavaScript and CSS
config/ contains frontend configurations
controllers/ contains Web controller classes
models/ contains frontend-specific model classes
runtime/ contains files generated during runtime
views/ contains view files for the Web application
web/ contains the entry script and Web resources
widgets/ contains frontend widgets
vendor/ contains dependent 3rd-party packages
environments/ contains environment-based overrides
tests contains various tests for the advanced application
codeception/ contains tests developed with Codeception PHP Testing Framework
```

29
api/assets/AppAsset.php Normal file
View File

@ -0,0 +1,29 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace api\assets;
use yii\web\AssetBundle;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class AppAsset extends AssetBundle
{
public $basePath = '@webroot';
public $baseUrl = '@web';
public $css = [
'css/site.css',
];
public $js = [
];
public $depends = [
'yii\web\YiiAsset',
'yii\bootstrap\BootstrapAsset',
];
}

2
api/config/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
main-local.php
params-local.php

1
api/config/bootstrap.php Normal file
View File

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

33
api/config/main.php Normal file
View File

@ -0,0 +1,33 @@
<?php
$params = array_merge(
require(__DIR__ . '/../../common/config/params.php'),
require(__DIR__ . '/../../common/config/params-local.php'),
require(__DIR__ . '/params.php'),
require(__DIR__ . '/params-local.php')
);
return [
'id' => 'accounts-site-api',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'controllerNamespace' => 'api\controllers',
'components' => [
'user' => [
'identityClass' => 'common\models\User',
'enableAutoLogin' => true,
],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
'errorHandler' => [
'errorAction' => 'site/error',
],
],
'params' => $params,
];

4
api/config/params.php Normal file
View File

@ -0,0 +1,4 @@
<?php
return [
'adminEmail' => 'admin@example.com',
];

View File

@ -0,0 +1,213 @@
<?php
namespace api\controllers;
use Yii;
use common\models\LoginForm;
use api\models\PasswordResetRequestForm;
use api\models\ResetPasswordForm;
use api\models\SignupForm;
use api\models\ContactForm;
use yii\base\InvalidParamException;
use yii\web\BadRequestHttpException;
use yii\web\Controller;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
/**
* Site controller
*/
class SiteController extends Controller
{
/**
* @inheritdoc
*/
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'only' => ['logout', 'signup'],
'rules' => [
[
'actions' => ['signup'],
'allow' => true,
'roles' => ['?'],
],
[
'actions' => ['logout'],
'allow' => true,
'roles' => ['@'],
],
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
/**
* @inheritdoc
*/
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
],
'captcha' => [
'class' => 'yii\captcha\CaptchaAction',
'fixedVerifyCode' => YII_ENV_TEST ? 'testme' : null,
],
];
}
/**
* Displays homepage.
*
* @return mixed
*/
public function actionIndex()
{
return $this->render('index');
}
/**
* Logs in a user.
*
* @return mixed
*/
public function actionLogin()
{
if (!\Yii::$app->user->isGuest) {
return $this->goHome();
}
$model = new LoginForm();
if ($model->load(Yii::$app->request->post()) && $model->login()) {
return $this->goBack();
} else {
return $this->render('login', [
'model' => $model,
]);
}
}
/**
* Logs out the current user.
*
* @return mixed
*/
public function actionLogout()
{
Yii::$app->user->logout();
return $this->goHome();
}
/**
* Displays contact page.
*
* @return mixed
*/
public function actionContact()
{
$model = new ContactForm();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
if ($model->sendEmail(Yii::$app->params['adminEmail'])) {
Yii::$app->session->setFlash('success', 'Thank you for contacting us. We will respond to you as soon as possible.');
} else {
Yii::$app->session->setFlash('error', 'There was an error sending email.');
}
return $this->refresh();
} else {
return $this->render('contact', [
'model' => $model,
]);
}
}
/**
* Displays about page.
*
* @return mixed
*/
public function actionAbout()
{
return $this->render('about');
}
/**
* Signs user up.
*
* @return mixed
*/
public function actionSignup()
{
$model = new SignupForm();
if ($model->load(Yii::$app->request->post())) {
if ($user = $model->signup()) {
if (Yii::$app->getUser()->login($user)) {
return $this->goHome();
}
}
}
return $this->render('signup', [
'model' => $model,
]);
}
/**
* Requests password reset.
*
* @return mixed
*/
public function actionRequestPasswordReset()
{
$model = new PasswordResetRequestForm();
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
if ($model->sendEmail()) {
Yii::$app->session->setFlash('success', 'Check your email for further instructions.');
return $this->goHome();
} else {
Yii::$app->session->setFlash('error', 'Sorry, we are unable to reset password for email provided.');
}
}
return $this->render('requestPasswordResetToken', [
'model' => $model,
]);
}
/**
* Resets password.
*
* @param string $token
* @return mixed
* @throws BadRequestHttpException
*/
public function actionResetPassword($token)
{
try {
$model = new ResetPasswordForm($token);
} catch (InvalidParamException $e) {
throw new BadRequestHttpException($e->getMessage());
}
if ($model->load(Yii::$app->request->post()) && $model->validate() && $model->resetPassword()) {
Yii::$app->session->setFlash('success', 'New password was saved.');
return $this->goHome();
}
return $this->render('resetPassword', [
'model' => $model,
]);
}
}

View File

@ -0,0 +1,59 @@
<?php
namespace api\models;
use Yii;
use yii\base\Model;
/**
* ContactForm is the model behind the contact form.
*/
class ContactForm extends Model
{
public $name;
public $email;
public $subject;
public $body;
public $verifyCode;
/**
* @inheritdoc
*/
public function rules()
{
return [
// name, email, subject and body are required
[['name', 'email', 'subject', 'body'], 'required'],
// email has to be a valid email address
['email', 'email'],
// verifyCode needs to be entered correctly
['verifyCode', 'captcha'],
];
}
/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'verifyCode' => 'Verification Code',
];
}
/**
* Sends an email to the specified email address using the information collected by this model.
*
* @param string $email the target email address
* @return boolean whether the email was sent
*/
public function sendEmail($email)
{
return Yii::$app->mailer->compose()
->setTo($email)
->setFrom([$this->email => $this->name])
->setSubject($this->subject)
->setTextBody($this->body)
->send();
}
}

View File

@ -0,0 +1,60 @@
<?php
namespace api\models;
use common\models\User;
use yii\base\Model;
/**
* Password reset request form
*/
class PasswordResetRequestForm extends Model
{
public $email;
/**
* @inheritdoc
*/
public function rules()
{
return [
['email', 'filter', 'filter' => 'trim'],
['email', 'required'],
['email', 'email'],
['email', 'exist',
'targetClass' => '\common\models\User',
'filter' => ['status' => User::STATUS_ACTIVE],
'message' => 'There is no user with such email.'
],
];
}
/**
* Sends an email with a link, for resetting the password.
*
* @return boolean whether the email was send
*/
public function sendEmail()
{
/* @var $user User */
$user = User::findOne([
'status' => User::STATUS_ACTIVE,
'email' => $this->email,
]);
if ($user) {
if (!User::isPasswordResetTokenValid($user->password_reset_token)) {
$user->generatePasswordResetToken();
}
if ($user->save()) {
return \Yii::$app->mailer->compose(['html' => 'passwordResetToken-html', 'text' => 'passwordResetToken-text'], ['user' => $user])
->setFrom([\Yii::$app->params['supportEmail'] => \Yii::$app->name . ' robot'])
->setTo($this->email)
->setSubject('Password reset for ' . \Yii::$app->name)
->send();
}
}
return false;
}
}

View File

@ -0,0 +1,65 @@
<?php
namespace api\models;
use common\models\User;
use yii\base\InvalidParamException;
use yii\base\Model;
use Yii;
/**
* Password reset form
*/
class ResetPasswordForm extends Model
{
public $password;
/**
* @var \common\models\User
*/
private $_user;
/**
* Creates a form model given a token.
*
* @param string $token
* @param array $config name-value pairs that will be used to initialize the object properties
* @throws \yii\base\InvalidParamException if token is empty or not valid
*/
public function __construct($token, $config = [])
{
if (empty($token) || !is_string($token)) {
throw new InvalidParamException('Password reset token cannot be blank.');
}
$this->_user = User::findByPasswordResetToken($token);
if (!$this->_user) {
throw new InvalidParamException('Wrong password reset token.');
}
parent::__construct($config);
}
/**
* @inheritdoc
*/
public function rules()
{
return [
['password', 'required'],
['password', 'string', 'min' => 6],
];
}
/**
* Resets password.
*
* @return boolean if password was reset.
*/
public function resetPassword()
{
$user = $this->_user;
$user->setPassword($this->password);
$user->removePasswordResetToken();
return $user->save(false);
}
}

59
api/models/SignupForm.php Normal file
View File

@ -0,0 +1,59 @@
<?php
namespace api\models;
use common\models\User;
use yii\base\Model;
use Yii;
/**
* Signup form
*/
class SignupForm extends Model
{
public $username;
public $email;
public $password;
/**
* @inheritdoc
*/
public function rules()
{
return [
['username', 'filter', 'filter' => 'trim'],
['username', 'required'],
['username', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This username has already been taken.'],
['username', 'string', 'min' => 2, 'max' => 255],
['email', 'filter', 'filter' => 'trim'],
['email', 'required'],
['email', 'email'],
['email', 'string', 'max' => 255],
['email', 'unique', 'targetClass' => '\common\models\User', 'message' => 'This email address has already been taken.'],
['password', 'required'],
['password', 'string', 'min' => 6],
];
}
/**
* Signs user up.
*
* @return User|null the saved model or null if saving fails
*/
public function signup()
{
if ($this->validate()) {
$user = new User();
$user->username = $this->username;
$user->email = $this->email;
$user->setPassword($this->password);
$user->generateAuthKey();
if ($user->save()) {
return $user;
}
}
return null;
}
}

2
api/runtime/.gitignore vendored Normal file
View File

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

View File

@ -0,0 +1,77 @@
<?php
/* @var $this \yii\web\View */
/* @var $content string */
use yii\helpers\Html;
use yii\bootstrap\Nav;
use yii\bootstrap\NavBar;
use yii\widgets\Breadcrumbs;
use api\assets\AppAsset;
AppAsset::register($this);
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang="<?= Yii::$app->language ?>">
<head>
<meta charset="<?= Yii::$app->charset ?>">
<meta name="viewport" content="width=device-width, initial-scale=1">
<?= Html::csrfMetaTags() ?>
<title><?= Html::encode($this->title) ?></title>
<?php $this->head() ?>
</head>
<body>
<?php $this->beginBody() ?>
<div class="wrap">
<?php
NavBar::begin([
'brandLabel' => 'My Company',
'brandUrl' => Yii::$app->homeUrl,
'options' => [
'class' => 'navbar-inverse navbar-fixed-top',
],
]);
$menuItems = [
['label' => 'Home', 'url' => ['/site/index']],
['label' => 'About', 'url' => ['/site/about']],
['label' => 'Contact', 'url' => ['/site/contact']],
];
if (Yii::$app->user->isGuest) {
$menuItems[] = ['label' => 'Signup', 'url' => ['/site/signup']];
$menuItems[] = ['label' => 'Login', 'url' => ['/site/login']];
} else {
$menuItems[] = [
'label' => 'Logout (' . Yii::$app->user->identity->username . ')',
'url' => ['/site/logout'],
'linkOptions' => ['data-method' => 'post']
];
}
echo Nav::widget([
'options' => ['class' => 'navbar-nav navbar-right'],
'items' => $menuItems,
]);
NavBar::end();
?>
<div class="container">
<?= Breadcrumbs::widget([
'links' => isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [],
]) ?>
<?= $content ?>
</div>
</div>
<footer class="footer">
<div class="container">
<p class="pull-left">&copy; My Company <?= date('Y') ?></p>
<p class="pull-right"><?= Yii::powered() ?></p>
</div>
</footer>
<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage() ?>

16
api/views/site/about.php Normal file
View File

@ -0,0 +1,16 @@
<?php
/* @var $this yii\web\View */
use yii\helpers\Html;
$this->title = 'About';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-about">
<h1><?= Html::encode($this->title) ?></h1>
<p>This is the About page. You may modify the following file to customize its content:</p>
<code><?= __FILE__ ?></code>
</div>

View File

@ -0,0 +1,45 @@
<?php
/* @var $this yii\web\View */
/* @var $form yii\bootstrap\ActiveForm */
/* @var $model \api\models\ContactForm */
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
use yii\captcha\Captcha;
$this->title = 'Contact';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-contact">
<h1><?= Html::encode($this->title) ?></h1>
<p>
If you have business inquiries or other questions, please fill out the following form to contact us. Thank you.
</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'contact-form']); ?>
<?= $form->field($model, 'name') ?>
<?= $form->field($model, 'email') ?>
<?= $form->field($model, 'subject') ?>
<?= $form->field($model, 'body')->textArea(['rows' => 6]) ?>
<?= $form->field($model, 'verifyCode')->widget(Captcha::className(), [
'template' => '<div class="row"><div class="col-lg-3">{image}</div><div class="col-lg-6">{input}</div></div>',
]) ?>
<div class="form-group">
<?= Html::submitButton('Submit', ['class' => 'btn btn-primary', 'name' => 'contact-button']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>

27
api/views/site/error.php Normal file
View File

@ -0,0 +1,27 @@
<?php
/* @var $this yii\web\View */
/* @var $name string */
/* @var $message string */
/* @var $exception Exception */
use yii\helpers\Html;
$this->title = $name;
?>
<div class="site-error">
<h1><?= Html::encode($this->title) ?></h1>
<div class="alert alert-danger">
<?= nl2br(Html::encode($message)) ?>
</div>
<p>
The above error occurred while the Web server was processing your request.
</p>
<p>
Please contact us if you think this is a server error. Thank you.
</p>
</div>

53
api/views/site/index.php Normal file
View File

@ -0,0 +1,53 @@
<?php
/* @var $this yii\web\View */
$this->title = 'My Yii Application';
?>
<div class="site-index">
<div class="jumbotron">
<h1>Congratulations!</h1>
<p class="lead">You have successfully created your Yii-powered application.</p>
<p><a class="btn btn-lg btn-success" href="http://www.yiiframework.com">Get started with Yii</a></p>
</div>
<div class="body-content">
<div class="row">
<div class="col-lg-4">
<h2>Heading</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur.</p>
<p><a class="btn btn-default" href="http://www.yiiframework.com/doc/">Yii Documentation &raquo;</a></p>
</div>
<div class="col-lg-4">
<h2>Heading</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur.</p>
<p><a class="btn btn-default" href="http://www.yiiframework.com/forum/">Yii Forum &raquo;</a></p>
</div>
<div class="col-lg-4">
<h2>Heading</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et
dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip
ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur.</p>
<p><a class="btn btn-default" href="http://www.yiiframework.com/extensions/">Yii Extensions &raquo;</a></p>
</div>
</div>
</div>
</div>

39
api/views/site/login.php Normal file
View File

@ -0,0 +1,39 @@
<?php
/* @var $this yii\web\View */
/* @var $form yii\bootstrap\ActiveForm */
/* @var $model \common\models\LoginForm */
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
$this->title = 'Login';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-login">
<h1><?= Html::encode($this->title) ?></h1>
<p>Please fill out the following fields to login:</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'login-form']); ?>
<?= $form->field($model, 'username') ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<?= $form->field($model, 'rememberMe')->checkbox() ?>
<div style="color:#999;margin:1em 0">
If you forgot your password you can <?= Html::a('reset it', ['site/request-password-reset']) ?>.
</div>
<div class="form-group">
<?= Html::submitButton('Login', ['class' => 'btn btn-primary', 'name' => 'login-button']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>

View File

@ -0,0 +1,31 @@
<?php
/* @var $this yii\web\View */
/* @var $form yii\bootstrap\ActiveForm */
/* @var $model \api\models\PasswordResetRequestForm */
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
$this->title = 'Request password reset';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-request-password-reset">
<h1><?= Html::encode($this->title) ?></h1>
<p>Please fill out your email. A link to reset password will be sent there.</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'request-password-reset-form']); ?>
<?= $form->field($model, 'email') ?>
<div class="form-group">
<?= Html::submitButton('Send', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>

View File

@ -0,0 +1,31 @@
<?php
/* @var $this yii\web\View */
/* @var $form yii\bootstrap\ActiveForm */
/* @var $model \api\models\ResetPasswordForm */
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
$this->title = 'Reset password';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-reset-password">
<h1><?= Html::encode($this->title) ?></h1>
<p>Please choose your new password:</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'reset-password-form']); ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<div class="form-group">
<?= Html::submitButton('Save', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>

35
api/views/site/signup.php Normal file
View File

@ -0,0 +1,35 @@
<?php
/* @var $this yii\web\View */
/* @var $form yii\bootstrap\ActiveForm */
/* @var $model \api\models\SignupForm */
use yii\helpers\Html;
use yii\bootstrap\ActiveForm;
$this->title = 'Signup';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="site-signup">
<h1><?= Html::encode($this->title) ?></h1>
<p>Please fill out the following fields to signup:</p>
<div class="row">
<div class="col-lg-5">
<?php $form = ActiveForm::begin(['id' => 'form-signup']); ?>
<?= $form->field($model, 'username') ?>
<?= $form->field($model, 'email') ?>
<?= $form->field($model, 'password')->passwordInput() ?>
<div class="form-group">
<?= Html::submitButton('Signup', ['class' => 'btn btn-primary', 'name' => 'signup-button']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
</div>

2
api/web/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/index.php
/index-test.php

2
api/web/assets/.gitignore vendored Normal file
View File

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

BIN
api/web/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 318 B

2
api/web/robots.txt Normal file
View File

@ -0,0 +1,2 @@
User-agent: *
Disallow:

2
common/config/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
main-local.php
params-local.php

View File

@ -0,0 +1,4 @@
<?php
Yii::setAlias('common', dirname(__DIR__));
Yii::setAlias('api', dirname(dirname(__DIR__)) . '/api');
Yii::setAlias('console', dirname(dirname(__DIR__)) . '/console');

17
common/config/main.php Normal file
View File

@ -0,0 +1,17 @@
<?php
return [
'vendorPath' => dirname(dirname(__DIR__)) . '/vendor',
'components' => [
'cache' => [
'class' => 'yii\caching\FileCache',
],
'db' => [
'class' => 'yii\db\Connection',
'charset' => 'utf8',
],
'mailer' => [
'class' => 'yii\swiftmailer\Mailer',
'viewPath' => '@common/mail',
],
],
];

6
common/config/params.php Normal file
View File

@ -0,0 +1,6 @@
<?php
return [
'adminEmail' => 'admin@example.com',
'supportEmail' => 'support@example.com',
'user.passwordResetTokenExpire' => 3600,
];

View File

@ -0,0 +1,22 @@
<?php
use yii\helpers\Html;
/* @var $this \yii\web\View view component instance */
/* @var $message \yii\mail\MessageInterface the message being composed */
/* @var $content string main view render result */
?>
<?php $this->beginPage() ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=<?= Yii::$app->charset ?>" />
<title><?= Html::encode($this->title) ?></title>
<?php $this->head() ?>
</head>
<body>
<?php $this->beginBody() ?>
<?= $content ?>
<?php $this->endBody() ?>
</body>
</html>
<?php $this->endPage() ?>

View File

@ -0,0 +1,12 @@
<?php
use yii\helpers\Html;
/* @var $this \yii\web\View view component instance */
/* @var $message \yii\mail\MessageInterface the message being composed */
/* @var $content string main view render result */
?>
<?php $this->beginPage() ?>
<?php $this->beginBody() ?>
<?= $content ?>
<?php $this->endBody() ?>
<?php $this->endPage() ?>

View File

@ -0,0 +1,15 @@
<?php
use yii\helpers\Html;
/* @var $this yii\web\View */
/* @var $user common\models\User */
$resetLink = Yii::$app->urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]);
?>
<div class="password-reset">
<p>Hello <?= Html::encode($user->username) ?>,</p>
<p>Follow the link below to reset your password:</p>
<p><?= Html::a(Html::encode($resetLink), $resetLink) ?></p>
</div>

View File

@ -0,0 +1,12 @@
<?php
/* @var $this yii\web\View */
/* @var $user common\models\User */
$resetLink = Yii::$app->urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]);
?>
Hello <?= $user->username ?>,
Follow the link below to reset your password:
<?= $resetLink ?>

View File

@ -0,0 +1,78 @@
<?php
namespace common\models;
use Yii;
use yii\base\Model;
/**
* Login form
*/
class LoginForm extends Model
{
public $username;
public $password;
public $rememberMe = true;
private $_user;
/**
* @inheritdoc
*/
public function rules()
{
return [
// username and password are both required
[['username', 'password'], 'required'],
// rememberMe must be a boolean value
['rememberMe', 'boolean'],
// password is validated by validatePassword()
['password', 'validatePassword'],
];
}
/**
* Validates the password.
* This method serves as the inline validation for password.
*
* @param string $attribute the attribute currently being validated
* @param array $params the additional name-value pairs given in the rule
*/
public function validatePassword($attribute, $params)
{
if (!$this->hasErrors()) {
$user = $this->getUser();
if (!$user || !$user->validatePassword($this->password)) {
$this->addError($attribute, 'Incorrect username or password.');
}
}
}
/**
* Logs in a user using the provided username and password.
*
* @return boolean whether the user is logged in successfully
*/
public function login()
{
if ($this->validate()) {
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);
} else {
return false;
}
}
/**
* Finds user by [[username]]
*
* @return User|null
*/
protected function getUser()
{
if ($this->_user === null) {
$this->_user = User::findByUsername($this->username);
}
return $this->_user;
}
}

188
common/models/User.php Normal file
View File

@ -0,0 +1,188 @@
<?php
namespace common\models;
use Yii;
use yii\base\NotSupportedException;
use yii\behaviors\TimestampBehavior;
use yii\db\ActiveRecord;
use yii\web\IdentityInterface;
/**
* User model
*
* @property integer $id
* @property string $username
* @property string $password_hash
* @property string $password_reset_token
* @property string $email
* @property string $auth_key
* @property integer $status
* @property integer $created_at
* @property integer $updated_at
* @property string $password write-only password
*/
class User extends ActiveRecord implements IdentityInterface
{
const STATUS_DELETED = 0;
const STATUS_ACTIVE = 10;
/**
* @inheritdoc
*/
public static function tableName()
{
return '{{%user}}';
}
/**
* @inheritdoc
*/
public function behaviors()
{
return [
TimestampBehavior::className(),
];
}
/**
* @inheritdoc
*/
public function rules()
{
return [
['status', 'default', 'value' => self::STATUS_ACTIVE],
['status', 'in', 'range' => [self::STATUS_ACTIVE, self::STATUS_DELETED]],
];
}
/**
* @inheritdoc
*/
public static function findIdentity($id)
{
return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
}
/**
* @inheritdoc
*/
public static function findIdentityByAccessToken($token, $type = null)
{
throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
}
/**
* Finds user by username
*
* @param string $username
* @return static|null
*/
public static function findByUsername($username)
{
return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]);
}
/**
* Finds user by password reset token
*
* @param string $token password reset token
* @return static|null
*/
public static function findByPasswordResetToken($token)
{
if (!static::isPasswordResetTokenValid($token)) {
return null;
}
return static::findOne([
'password_reset_token' => $token,
'status' => self::STATUS_ACTIVE,
]);
}
/**
* Finds out if password reset token is valid
*
* @param string $token password reset token
* @return boolean
*/
public static function isPasswordResetTokenValid($token)
{
if (empty($token)) {
return false;
}
$timestamp = (int) substr($token, strrpos($token, '_') + 1);
$expire = Yii::$app->params['user.passwordResetTokenExpire'];
return $timestamp + $expire >= time();
}
/**
* @inheritdoc
*/
public function getId()
{
return $this->getPrimaryKey();
}
/**
* @inheritdoc
*/
public function getAuthKey()
{
return $this->auth_key;
}
/**
* @inheritdoc
*/
public function validateAuthKey($authKey)
{
return $this->getAuthKey() === $authKey;
}
/**
* Validates password
*
* @param string $password password to validate
* @return boolean if password provided is valid for current user
*/
public function validatePassword($password)
{
return Yii::$app->security->validatePassword($password, $this->password_hash);
}
/**
* Generates password hash from password and sets it to the model
*
* @param string $password
*/
public function setPassword($password)
{
$this->password_hash = Yii::$app->security->generatePasswordHash($password);
}
/**
* Generates "remember me" authentication key
*/
public function generateAuthKey()
{
$this->auth_key = Yii::$app->security->generateRandomString();
}
/**
* Generates new password reset token
*/
public function generatePasswordResetToken()
{
$this->password_reset_token = Yii::$app->security->generateRandomString() . '_' . time();
}
/**
* Removes password reset token
*/
public function removePasswordResetToken()
{
$this->password_reset_token = null;
}
}

37
composer.json Normal file
View File

@ -0,0 +1,37 @@
{
"name": "yiisoft/yii2-app-advanced",
"description": "Yii 2 Advanced Project Template",
"keywords": ["yii2", "framework", "advanced", "project template"],
"homepage": "http://www.yiiframework.com/",
"type": "project",
"license": "BSD-3-Clause",
"support": {
"issues": "https://github.com/yiisoft/yii2/issues?state=open",
"forum": "http://www.yiiframework.com/forum/",
"wiki": "http://www.yiiframework.com/wiki/",
"irc": "irc://irc.freenode.net/yii",
"source": "https://github.com/yiisoft/yii2"
},
"minimum-stability": "stable",
"require": {
"php": ">=5.4.0",
"yiisoft/yii2": ">=2.0.6",
"yiisoft/yii2-bootstrap": "*",
"yiisoft/yii2-swiftmailer": "*"
},
"require-dev": {
"yiisoft/yii2-codeception": "*",
"yiisoft/yii2-debug": "*",
"yiisoft/yii2-gii": "*",
"yiisoft/yii2-faker": "*"
},
"config": {
"process-timeout": 1800
},
"extra": {
"asset-installer-paths": {
"npm-asset-library": "vendor/npm",
"bower-asset-library": "vendor/bower"
}
}
}

2
console/config/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
main-local.php
params-local.php

View File

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

25
console/config/main.php Normal file
View File

@ -0,0 +1,25 @@
<?php
$params = array_merge(
require(__DIR__ . '/../../common/config/params.php'),
require(__DIR__ . '/../../common/config/params-local.php'),
require(__DIR__ . '/params.php'),
require(__DIR__ . '/params-local.php')
);
return [
'id' => 'app-console',
'basePath' => dirname(__DIR__),
'bootstrap' => ['log'],
'controllerNamespace' => 'console\controllers',
'components' => [
'log' => [
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
],
'params' => $params,
];

View File

@ -0,0 +1,4 @@
<?php
return [
'adminEmail' => 'admin@example.com',
];

View File

View File

@ -0,0 +1,34 @@
<?php
use yii\db\Schema;
use yii\db\Migration;
class m130524_201442_init extends Migration
{
public function up()
{
$tableOptions = null;
if ($this->db->driverName === 'mysql') {
// http://stackoverflow.com/questions/766809/whats-the-difference-between-utf8-general-ci-and-utf8-unicode-ci
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
}
$this->createTable('{{%user}}', [
'id' => $this->primaryKey(),
'username' => $this->string()->notNull()->unique(),
'auth_key' => $this->string(32)->notNull(),
'password_hash' => $this->string()->notNull(),
'password_reset_token' => $this->string()->unique(),
'email' => $this->string()->notNull()->unique(),
'status' => $this->smallInteger()->notNull()->defaultValue(10),
'created_at' => $this->integer()->notNull(),
'updated_at' => $this->integer()->notNull(),
], $tableOptions);
}
public function down()
{
$this->dropTable('{{%user}}');
}
}

1
console/models/.gitkeep Normal file
View File

@ -0,0 +1 @@
*

2
console/runtime/.gitignore vendored Normal file
View File

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

View File

@ -0,0 +1,21 @@
<?php
$config = [
'components' => [
'request' => [
// !!! insert a secret key in the following (if it is empty) - this is required by cookie validation
'cookieValidationKey' => '',
],
],
];
if (!YII_ENV_TEST) {
// configuration adjustments for 'dev' environment
$config['bootstrap'][] = 'debug';
$config['modules']['debug'] = 'yii\debug\Module';
$config['bootstrap'][] = 'gii';
$config['modules']['gii'] = 'yii\gii\Module';
}
return $config;

View File

@ -0,0 +1,3 @@
<?php
return [
];

View File

@ -0,0 +1,18 @@
<?php
// NOTE: Make sure this file is not accessible when deployed to production
if (!in_array(@$_SERVER['REMOTE_ADDR'], ['127.0.0.1', '::1'])) {
die('You are not allowed to access this file.');
}
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');
require(__DIR__ . '/../../common/config/bootstrap.php');
require(__DIR__ . '/../config/bootstrap.php');
$config = require(__DIR__ . '/../../tests/codeception/config/api/acceptance.php');
(new yii\web\Application($config))->run();

View File

@ -0,0 +1,18 @@
<?php
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');
require(__DIR__ . '/../../vendor/autoload.php');
require(__DIR__ . '/../../vendor/yiisoft/yii2/Yii.php');
require(__DIR__ . '/../../common/config/bootstrap.php');
require(__DIR__ . '/../config/bootstrap.php');
$config = 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')
);
$application = new yii\web\Application($config);
$application->run();

View File

@ -0,0 +1,16 @@
<?php
return [
'components' => [
'db' => [
'dsn' => 'mysql:host=localhost;dbname=ely_accounts',
'username' => 'root',
'password' => '',
],
'mailer' => [
// send all mails to a file by default. You have to set
// 'useFileTransport' to false and configure a transport
// for the mailer to send real emails.
'useFileTransport' => true,
],
],
];

View File

@ -0,0 +1,3 @@
<?php
return [
];

View File

@ -0,0 +1,7 @@
<?php
return [
'bootstrap' => ['gii'],
'modules' => [
'gii' => 'yii\gii\Module',
],
];

View File

@ -0,0 +1,3 @@
<?php
return [
];

28
environments/dev/yii Normal file
View File

@ -0,0 +1,28 @@
#!/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', 'dev');
require(__DIR__ . '/vendor/autoload.php');
require(__DIR__ . '/vendor/yiisoft/yii2/Yii.php');
require(__DIR__ . '/common/config/bootstrap.php');
require(__DIR__ . '/console/config/bootstrap.php');
$config = 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')
);
$application = new yii\console\Application($config);
$exitCode = $application->run();
exit($exitCode);

59
environments/index.php Normal file
View File

@ -0,0 +1,59 @@
<?php
/**
* The manifest of files that are local to specific environment.
* This file returns a list of environments that the application
* may be installed under. The returned data must be in the following
* format:
*
* ```php
* return [
* 'environment name' => [
* 'path' => 'directory storing the local files',
* 'skipFiles' => [
* // list of files that should only copied once and skipped if they already exist
* ],
* 'setWritable' => [
* // list of directories that should be set writable
* ],
* 'setExecutable' => [
* // list of files that should be set executable
* ],
* 'setCookieValidationKey' => [
* // list of config files that need to be inserted with automatically generated cookie validation keys
* ],
* 'createSymlink' => [
* // list of symlinks to be created. Keys are symlinks, and values are the targets.
* ],
* ],
* ];
* ```
*/
return [
'Development' => [
'path' => 'dev',
'setWritable' => [
'api/runtime',
'api/web/assets',
],
'setExecutable' => [
'yii',
'tests/codeception/bin/yii',
],
'setCookieValidationKey' => [
'api/config/main-local.php',
],
],
'Production' => [
'path' => 'prod',
'setWritable' => [
'api/runtime',
'api/web/assets',
],
'setExecutable' => [
'yii',
],
'setCookieValidationKey' => [
'api/config/main-local.php',
],
],
];

View File

@ -0,0 +1,10 @@
<?php
return [
'components' => [
'db' => [
'dsn' => 'mysql:host=localhost;dbname=ely_accounts',
'username' => 'root',
'password' => '',
],
],
];

View File

@ -0,0 +1,3 @@
<?php
return [
];

View File

@ -0,0 +1,3 @@
<?php
return [
];

View File

@ -0,0 +1,3 @@
<?php
return [
];

28
environments/prod/yii Normal file
View File

@ -0,0 +1,28 @@
#!/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', false);
defined('YII_ENV') or define('YII_ENV', 'prod');
require(__DIR__ . '/vendor/autoload.php');
require(__DIR__ . '/vendor/yiisoft/yii2/Yii.php');
require(__DIR__ . '/common/config/bootstrap.php');
require(__DIR__ . '/console/config/bootstrap.php');
$config = 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')
);
$application = new yii\console\Application($config);
$exitCode = $application->run();
exit($exitCode);

209
init Normal file
View File

@ -0,0 +1,209 @@
#!/usr/bin/env php
<?php
/**
* Yii Application Initialization Tool
*
* In order to run in non-interactive mode:
*
* init --env=Development --overwrite=n
*
* @author Alexander Makarov <sam@rmcreative.ru>
*
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
if (!extension_loaded('openssl')) {
die('The OpenSSL PHP extension is required by Yii2.');
}
$params = getParams();
$root = str_replace('\\', '/', __DIR__);
$envs = require("$root/environments/index.php");
$envNames = array_keys($envs);
echo "Yii Application Initialization Tool v1.0\n\n";
$envName = null;
if (empty($params['env']) || $params['env'] === '1') {
echo "Which environment do you want the application to be initialized in?\n\n";
foreach ($envNames as $i => $name) {
echo " [$i] $name\n";
}
echo "\n Your choice [0-" . (count($envs) - 1) . ', or "q" to quit] ';
$answer = trim(fgets(STDIN));
if (!ctype_digit($answer) || !in_array($answer, range(0, count($envs) - 1))) {
echo "\n Quit initialization.\n";
exit(0);
}
if (isset($envNames[$answer])) {
$envName = $envNames[$answer];
}
} else {
$envName = $params['env'];
}
if (!in_array($envName, $envNames)) {
$envsList = implode(', ', $envNames);
echo "\n $envName is not a valid environment. Try one of the following: $envsList. \n";
exit(2);
}
$env = $envs[$envName];
if (empty($params['env'])) {
echo "\n Initialize the application under '{$envNames[$answer]}' environment? [yes|no] ";
$answer = trim(fgets(STDIN));
if (strncasecmp($answer, 'y', 1)) {
echo "\n Quit initialization.\n";
exit(0);
}
}
echo "\n Start initialization ...\n\n";
$files = getFileList("$root/environments/{$env['path']}");
if (isset($env['skipFiles'])) {
$skipFiles = $env['skipFiles'];
array_walk($skipFiles, function(&$value) use($env, $root) { $value = "$root/$value"; });
$files = array_diff($files, array_intersect_key($env['skipFiles'], array_filter($skipFiles, 'file_exists')));
}
$all = false;
foreach ($files as $file) {
if (!copyFile($root, "environments/{$env['path']}/$file", $file, $all, $params)) {
break;
}
}
$callbacks = ['setCookieValidationKey', 'setWritable', 'setExecutable', 'createSymlink'];
foreach ($callbacks as $callback) {
if (!empty($env[$callback])) {
$callback($root, $env[$callback]);
}
}
echo "\n ... initialization completed.\n\n";
function getFileList($root, $basePath = '')
{
$files = [];
$handle = opendir($root);
while (($path = readdir($handle)) !== false) {
if ($path === '.git' || $path === '.svn' || $path === '.' || $path === '..') {
continue;
}
$fullPath = "$root/$path";
$relativePath = $basePath === '' ? $path : "$basePath/$path";
if (is_dir($fullPath)) {
$files = array_merge($files, getFileList($fullPath, $relativePath));
} else {
$files[] = $relativePath;
}
}
closedir($handle);
return $files;
}
function copyFile($root, $source, $target, &$all, $params)
{
if (!is_file($root . '/' . $source)) {
echo " skip $target ($source not exist)\n";
return true;
}
if (is_file($root . '/' . $target)) {
if (file_get_contents($root . '/' . $source) === file_get_contents($root . '/' . $target)) {
echo " unchanged $target\n";
return true;
}
if ($all) {
echo " overwrite $target\n";
} else {
echo " exist $target\n";
echo " ...overwrite? [Yes|No|All|Quit] ";
$answer = !empty($params['overwrite']) ? $params['overwrite'] : trim(fgets(STDIN));
if (!strncasecmp($answer, 'q', 1)) {
return false;
} else {
if (!strncasecmp($answer, 'y', 1)) {
echo " overwrite $target\n";
} else {
if (!strncasecmp($answer, 'a', 1)) {
echo " overwrite $target\n";
$all = true;
} else {
echo " skip $target\n";
return true;
}
}
}
}
file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source));
return true;
}
echo " generate $target\n";
@mkdir(dirname($root . '/' . $target), 0777, true);
file_put_contents($root . '/' . $target, file_get_contents($root . '/' . $source));
return true;
}
function getParams()
{
$rawParams = [];
if (isset($_SERVER['argv'])) {
$rawParams = $_SERVER['argv'];
array_shift($rawParams);
}
$params = [];
foreach ($rawParams as $param) {
if (preg_match('/^--(\w+)(=(.*))?$/', $param, $matches)) {
$name = $matches[1];
$params[$name] = isset($matches[3]) ? $matches[3] : true;
} else {
$params[] = $param;
}
}
return $params;
}
function setWritable($root, $paths)
{
foreach ($paths as $writable) {
echo " chmod 0777 $writable\n";
@chmod("$root/$writable", 0777);
}
}
function setExecutable($root, $paths)
{
foreach ($paths as $executable) {
echo " chmod 0755 $executable\n";
@chmod("$root/$executable", 0755);
}
}
function setCookieValidationKey($root, $paths)
{
foreach ($paths as $file) {
echo " generate cookie validation key in $file\n";
$file = $root . '/' . $file;
$length = 32;
$bytes = openssl_random_pseudo_bytes($length);
$key = strtr(substr(base64_encode($bytes), 0, $length), '+/=', '_-.');
$content = preg_replace('/(("|\')cookieValidationKey("|\')\s*=>\s*)(""|\'\')/', "\\1'$key'", file_get_contents($file));
file_put_contents($file, $content);
}
}
function createSymlink($root, $links) {
foreach ($links as $link => $target) {
echo " symlink " . $root . "/" . $target . " " . $root . "/" . $link . "\n";
//first removing folders to avoid errors if the folder already exists
@rmdir($root . "/" . $link);
@symlink($root . "/" . $target, $root . "/" . $link);
}
}

20
init.bat Normal file
View File

@ -0,0 +1,20 @@
@echo off
rem -------------------------------------------------------------
rem Yii command line init script for Windows.
rem
rem @author Qiang Xue <qiang.xue@gmail.com>
rem @link http://www.yiiframework.com/
rem @copyright Copyright (c) 2008 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%init" %*
@endlocal

58
tests/README.md Normal file
View File

@ -0,0 +1,58 @@
This directory contains various tests for the advanced applications.
Tests in `codeception` directory are developed with [Codeception PHP Testing Framework](http://codeception.com/).
After creating and setting up the advanced 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.*" "codeception/specify=*" "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 you'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_advanced_tests` database then update it by applying migrations:
```
codeception/bin/yii migrate
```
4. In order to be able to run acceptance tests you need to start a webserver. The simplest way is to use PHP built in
webserver. In the root directory where `common`, `frontend` etc. are execute the following:
```
php -S localhost:8080
```
5. Now you can run the tests with the following commands, assuming you are in the `tests/codeception` directory:
```
# frontend tests
cd frontend
codecept build
codecept run
# backend tests
cd backend
codecept build
codecept run
# etc.
```
If you already have run `codecept build` for each application, you can skip that step and run all tests by a single `codecept run`.

10
tests/codeception.yml Normal file
View File

@ -0,0 +1,10 @@
include:
- codeception/common
- codeception/console
- codeception/api
paths:
log: codeception/_output
settings:
colors: true

2
tests/codeception/_output/.gitignore vendored Normal file
View File

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

4
tests/codeception/api/.gitignore vendored Normal file
View File

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

View File

@ -0,0 +1,23 @@
<?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__))));
defined('API_ENTRY_URL') or define('API_ENTRY_URL', parse_url(\Codeception\Configuration::config()['config']['test_entry_url'], PHP_URL_PATH));
defined('API_ENTRY_FILE') or define('API_ENTRY_FILE', YII_APP_BASE_PATH . '/api/web/index-test.php');
require_once(YII_APP_BASE_PATH . '/vendor/autoload.php');
require_once(YII_APP_BASE_PATH . '/vendor/yiisoft/yii2/Yii.php');
require_once(YII_APP_BASE_PATH . '/common/config/bootstrap.php');
require_once(YII_APP_BASE_PATH . '/api/config/bootstrap.php');
// set correct script paths
// the entry script file path for functional and acceptance tests
$_SERVER['SCRIPT_FILENAME'] = API_ENTRY_FILE;
$_SERVER['SCRIPT_NAME'] = API_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(dirname(__DIR__)));

View File

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

View File

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

View File

@ -0,0 +1,26 @@
<?php
namespace tests\codeception\api\_pages;
use yii\codeception\BasePage;
/**
* Represents contact page
* @property \codeception_api\AcceptanceTester|\codeception_api\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

@ -0,0 +1,27 @@
<?php
namespace tests\codeception\api\_pages;
use \yii\codeception\BasePage;
/**
* Represents signup page
* @property \codeception_api\AcceptanceTester|\codeception_api\FunctionalTester $actor
*/
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->actor->fillField($inputType . '[name="SignupForm[' . $field . ']"]', $value);
}
$this->actor->click('signup-button');
}
}

View File

@ -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: AcceptanceTester
modules:
enabled:
- PhpBrowser
- tests\codeception\common\_support\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:
# 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

@ -0,0 +1,10 @@
<?php
use tests\codeception\api\AcceptanceTester;
use tests\codeception\api\_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

@ -0,0 +1,56 @@
<?php
use tests\codeception\api\AcceptanceTester;
use tests\codeception\api\_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', '.help-block');
$I->see('Email cannot be blank', '.help-block');
$I->see('Subject cannot be blank', '.help-block');
$I->see('Body cannot be blank', '.help-block');
$I->see('The verification code is incorrect', '.help-block');
$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 adress is wrong');
$I->dontSee('Name cannot be blank', '.help-block');
$I->see('Email is not a valid email address.', '.help-block');
$I->dontSee('Subject cannot be blank', '.help-block');
$I->dontSee('Body cannot be blank', '.help-block');
$I->dontSee('The verification code is incorrect', '.help-block');
$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->see('Thank you for contacting us. We will respond to you as soon as possible.');

View File

@ -0,0 +1,12 @@
<?php
use tests\codeception\api\AcceptanceTester;
/* @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

@ -0,0 +1,34 @@
<?php
use tests\codeception\api\AcceptanceTester;
use tests\codeception\common\_pages\LoginPage;
/* @var $scenario Codeception\Scenario */
$I = new AcceptanceTester($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.', '.help-block');
$I->see('Password cannot be blank.', '.help-block');
$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.', '.help-block');
$I->amGoingTo('try to login with correct credentials');
$loginPage->login('erau', 'password_0');
$I->expectTo('see that user is logged');
$I->seeLink('Logout (erau)');
$I->dontSeeLink('Login');
$I->dontSeeLink('Signup');
/** Uncomment if using WebDriver
* $I->click('Logout (erau)');
* $I->dontSeeLink('Logout (erau)');
* $I->seeLink('Login');
*/

View File

@ -0,0 +1,82 @@
<?php
namespace tests\codeception\api\acceptance;
use tests\codeception\api\_pages\SignupPage;
use common\models\User;
class SignupCest
{
/**
* This method is called before each cest class test method
* @param \Codeception\Event\TestEvent $event
*/
public function _before($event)
{
}
/**
* This method is called after each cest class test method, even if test failed.
* @param \Codeception\Event\TestEvent $event
*/
public function _after($event)
{
User::deleteAll([
'email' => 'tester.email@example.com',
'username' => 'tester',
]);
}
/**
* This method is called when test fails.
* @param \Codeception\Event\FailEvent $event
*/
public function _fail($event)
{
}
/**
* @param \codeception_api\AcceptanceTester $I
* @param \Codeception\Scenario $scenario
*/
public function testUserSignup($I, $scenario)
{
$I->wantTo('ensure that signup works');
$signupPage = SignupPage::openBy($I);
$I->see('Signup', 'h1');
$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.', '.help-block');
$I->see('Email cannot be blank.', '.help-block');
$I->see('Password cannot be blank.', '.help-block');
$I->amGoingTo('submit signup form with not correct email');
$signupPage->submit([
'username' => 'tester',
'email' => 'tester.email',
'password' => 'tester_password',
]);
$I->expectTo('see that email address is wrong');
$I->dontSee('Username cannot be blank.', '.help-block');
$I->dontSee('Password cannot be blank.', '.help-block');
$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->seeLink('Logout (tester)');
}
}

View File

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

View File

@ -0,0 +1,17 @@
namespace: tests\codeception\api
actor: Tester
paths:
tests: .
log: _output
data: _data
helpers: _support
settings:
bootstrap: _bootstrap.php
suite_class: \PHPUnit_Framework_TestSuite
colors: true
memory_limit: 1024M
log: 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/api/web/index-test.php

View File

@ -0,0 +1,17 @@
# 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: FunctionalTester
modules:
enabled:
- Filesystem
- Yii2
- tests\codeception\common\_support\FixtureHelper
config:
Yii2:
configFile: '../config/api/functional.php'

View File

@ -0,0 +1,10 @@
<?php
use tests\codeception\api\FunctionalTester;
use tests\codeception\api\_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

@ -0,0 +1,47 @@
<?php
use tests\codeception\api\FunctionalTester;
use tests\codeception\api\_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', '.help-block');
$I->see('Email cannot be blank', '.help-block');
$I->see('Subject cannot be blank', '.help-block');
$I->see('Body cannot be blank', '.help-block');
$I->see('The verification code is incorrect', '.help-block');
$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-block');
$I->see('Email is not a valid email address.', '.help-block');
$I->dontSee('Subject cannot be blank', '.help-block');
$I->dontSee('Body cannot be blank', '.help-block');
$I->dontSee('The verification code is incorrect', '.help-block');
$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.');

View File

@ -0,0 +1,12 @@
<?php
use tests\codeception\api\FunctionalTester;
/* @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

@ -0,0 +1,29 @@
<?php
use tests\codeception\api\FunctionalTester;
use tests\codeception\common\_pages\LoginPage;
/* @var $scenario Codeception\Scenario */
$I = new FunctionalTester($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.', '.help-block');
$I->see('Password cannot be blank.', '.help-block');
$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.', '.help-block');
$I->amGoingTo('try to login with correct credentials');
$loginPage->login('erau', 'password_0');
$I->expectTo('see that user is logged');
$I->seeLink('Logout (erau)');
$I->dontSeeLink('Login');
$I->dontSeeLink('Signup');

View File

@ -0,0 +1,90 @@
<?php
namespace tests\codeception\api\functional;
use tests\codeception\api\_pages\SignupPage;
use common\models\User;
class SignupCest
{
/**
* This method is called before each cest class test method
* @param \Codeception\Event\TestEvent $event
*/
public function _before($event)
{
}
/**
* This method is called after each cest class test method, even if test failed.
* @param \Codeception\Event\TestEvent $event
*/
public function _after($event)
{
User::deleteAll([
'email' => 'tester.email@example.com',
'username' => 'tester',
]);
}
/**
* This method is called when test fails.
* @param \Codeception\Event\FailEvent $event
*/
public function _fail($event)
{
}
/**
*
* @param \codeception_api\FunctionalTester $I
* @param \Codeception\Scenario $scenario
*/
public function testUserSignup($I, $scenario)
{
$I->wantTo('ensure that signup works');
$signupPage = SignupPage::openBy($I);
$I->see('Signup', 'h1');
$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.', '.help-block');
$I->see('Email cannot be blank.', '.help-block');
$I->see('Password cannot be blank.', '.help-block');
$I->amGoingTo('submit signup form with not correct email');
$signupPage->submit([
'username' => 'tester',
'email' => 'tester.email',
'password' => 'tester_password',
]);
$I->expectTo('see that email address is wrong');
$I->dontSee('Username cannot be blank.', '.help-block');
$I->dontSee('Password cannot be blank.', '.help-block');
$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 is created');
$I->seeRecord('common\models\User', [
'username' => 'tester',
'email' => 'tester.email@example.com',
]);
$I->expectTo('see that user logged in');
$I->seeLink('Logout (tester)');
}
}

View File

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

View File

@ -0,0 +1,6 @@
# Codeception Test Suite Configuration
# suite for unit (internal) tests.
# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.
class_name: UnitTester

View File

@ -0,0 +1,11 @@
<?php
namespace tests\codeception\api\unit;
/**
* @inheritdoc
*/
class DbTestCase extends \yii\codeception\DbTestCase
{
public $appConfig = '@tests/codeception/config/api/unit.php';
}

View File

@ -0,0 +1,11 @@
<?php
namespace tests\codeception\api\unit;
/**
* @inheritdoc
*/
class TestCase extends \yii\codeception\TestCase
{
public $appConfig = '@tests/codeception/config/api/unit.php';
}

View File

@ -0,0 +1,2 @@
<?php
// Here you can initialize variables that will for your tests

View File

@ -0,0 +1,23 @@
<?php
return [
[
'username' => 'okirlin',
'auth_key' => 'iwTNae9t34OmnK6l4vT4IeaTk-YWI2Rv',
'password_hash' => '$2y$13$CXT0Rkle1EMJ/c1l5bylL.EylfmQ39O5JlHJVFpNn618OUS1HwaIi',
'password_reset_token' => 't5GU9NwpuGYSfb7FEZMAxqtuz2PkEvv_' . time(),
'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_' . time(),
'created_at' => '1391885313',
'updated_at' => '1391885313',
'email' => 'nicolas.dianna@hotmail.com',
'status' => '0',
],
];

View File

@ -0,0 +1,59 @@
<?php
namespace tests\codeception\api\unit\models;
use Yii;
use tests\codeception\api\unit\TestCase;
use api\models\ContactForm;
class ContactFormTest extends TestCase
{
use \Codeception\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()
{
$model = new ContactForm();
$model->attributes = [
'name' => 'Tester',
'email' => 'tester@example.com',
'subject' => 'very important letter subject',
'body' => 'body of current message',
];
$model->sendEmail('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->mailer->fileTransportPath) . '/testing_message.eml';
}
}

View File

@ -0,0 +1,87 @@
<?php
namespace tests\codeception\api\models;
use Yii;
use tests\codeception\api\unit\DbTestCase;
use api\models\PasswordResetRequestForm;
use tests\codeception\common\fixtures\UserFixture;
use common\models\User;
use Codeception\Specify;
class PasswordResetRequestFormTest extends DbTestCase
{
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 testSendEmailWrongUser()
{
$this->specify('no user with such email, message should not be sent', function () {
$model = new PasswordResetRequestForm();
$model->email = 'not-existing-email@example.com';
expect('email not sent', $model->sendEmail())->false();
});
$this->specify('user is not active, message should not be sent', function () {
$model = new PasswordResetRequestForm();
$model->email = $this->user[1]['email'];
expect('email not sent', $model->sendEmail())->false();
});
}
public function testSendEmailCorrectUser()
{
$model = new PasswordResetRequestForm();
$model->email = $this->user[0]['email'];
$user = User::findOne(['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' => '@tests/codeception/api/unit/fixtures/data/models/user.php'
],
];
}
private function getMessageFile()
{
return Yii::getAlias(Yii::$app->mailer->fileTransportPath) . '/testing_message.eml';
}
}

View File

@ -0,0 +1,43 @@
<?php
namespace tests\codeception\api\unit\models;
use tests\codeception\api\unit\DbTestCase;
use tests\codeception\common\fixtures\UserFixture;
use api\models\ResetPasswordForm;
class ResetPasswordFormTest extends DbTestCase
{
/**
* @expectedException \yii\base\InvalidParamException
*/
public function testResetWrongToken()
{
new ResetPasswordForm('notexistingtoken_1391882543');
}
/**
* @expectedException \yii\base\InvalidParamException
*/
public function testResetEmptyToken()
{
new ResetPasswordForm('');
}
public function testResetCorrectToken()
{
$form = new ResetPasswordForm($this->user[0]['password_reset_token']);
expect('password should be resetted', $form->resetPassword())->true();
}
public function fixtures()
{
return [
'user' => [
'class' => UserFixture::className(),
'dataFile' => '@tests/codeception/api/unit/fixtures/data/models/user.php'
],
];
}
}

View File

@ -0,0 +1,52 @@
<?php
namespace tests\codeception\api\unit\models;
use tests\codeception\api\unit\DbTestCase;
use tests\codeception\common\fixtures\UserFixture;
use Codeception\Specify;
use api\models\SignupForm;
class SignupFormTest extends DbTestCase
{
use Specify;
public function testCorrectSignup()
{
$model = new SignupForm([
'username' => 'some_username',
'email' => 'some_email@example.com',
'password' => 'some_password',
]);
$user = $model->signup();
$this->assertInstanceOf('common\models\User', $user, 'user should be valid');
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 = new SignupForm([
'username' => 'troy.becker',
'email' => 'nicolas.dianna@hotmail.com',
'password' => 'some_password',
]);
expect('username and email are in use, user should not be created', $model->signup())->null();
}
public function fixtures()
{
return [
'user' => [
'class' => UserFixture::className(),
'dataFile' => '@tests/codeception/api/unit/fixtures/data/models/user.php',
],
];
}
}

View File

@ -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/
*/
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_once(YII_APP_BASE_PATH . '/vendor/autoload.php');
require_once(YII_APP_BASE_PATH . '/vendor/yiisoft/yii2/Yii.php');
require_once(YII_APP_BASE_PATH . '/common/config/bootstrap.php');
Yii::setAlias('@tests', dirname(dirname(__DIR__)));

23
tests/codeception/bin/yii Normal file
View File

@ -0,0 +1,23 @@
#!/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 . '/common/config/main.php'),
require(YII_APP_BASE_PATH . '/common/config/main-local.php'),
require(YII_APP_BASE_PATH . '/console/config/main.php'),
require(YII_APP_BASE_PATH . '/console/config/main-local.php'),
require(dirname(__DIR__) . '/config/config.php')
);
$application = new yii\console\Application($config);
$exitCode = $application->run();
exit($exitCode);

View File

@ -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 (c) 2008 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

4
tests/codeception/common/.gitignore vendored Normal file
View File

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

Some files were not shown because too many files have changed in this diff Show More