commit 841303b8ab2e36b9f2fef12de6cf90cf25a53446 Author: ErickSkrauch Date: Sat Jan 2 16:43:18 2016 +0300 Инициализировано Yii2 приложение, выпилены лишние части, накинуты чуточку нужных diff --git a/.bowerrc b/.bowerrc new file mode 100644 index 0000000..1669168 --- /dev/null +++ b/.bowerrc @@ -0,0 +1,3 @@ +{ + "directory" : "vendor/bower" +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..30507e4 --- /dev/null +++ b/.gitignore @@ -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 diff --git a/README.md b/README.md new file mode 100644 index 0000000..45e56ad --- /dev/null +++ b/README.md @@ -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 +``` diff --git a/api/assets/AppAsset.php b/api/assets/AppAsset.php new file mode 100644 index 0000000..e7e722f --- /dev/null +++ b/api/assets/AppAsset.php @@ -0,0 +1,29 @@ + + * @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', + ]; +} diff --git a/api/config/.gitignore b/api/config/.gitignore new file mode 100644 index 0000000..20da318 --- /dev/null +++ b/api/config/.gitignore @@ -0,0 +1,2 @@ +main-local.php +params-local.php \ No newline at end of file diff --git a/api/config/bootstrap.php b/api/config/bootstrap.php new file mode 100644 index 0000000..b3d9bbc --- /dev/null +++ b/api/config/bootstrap.php @@ -0,0 +1 @@ + '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, +]; diff --git a/api/config/params.php b/api/config/params.php new file mode 100644 index 0000000..7f754b9 --- /dev/null +++ b/api/config/params.php @@ -0,0 +1,4 @@ + 'admin@example.com', +]; diff --git a/api/controllers/SiteController.php b/api/controllers/SiteController.php new file mode 100644 index 0000000..c011ade --- /dev/null +++ b/api/controllers/SiteController.php @@ -0,0 +1,213 @@ + [ + '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, + ]); + } +} diff --git a/api/models/ContactForm.php b/api/models/ContactForm.php new file mode 100644 index 0000000..550c3b3 --- /dev/null +++ b/api/models/ContactForm.php @@ -0,0 +1,59 @@ + '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(); + } +} diff --git a/api/models/PasswordResetRequestForm.php b/api/models/PasswordResetRequestForm.php new file mode 100644 index 0000000..2ef15ba --- /dev/null +++ b/api/models/PasswordResetRequestForm.php @@ -0,0 +1,60 @@ + '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; + } +} diff --git a/api/models/ResetPasswordForm.php b/api/models/ResetPasswordForm.php new file mode 100644 index 0000000..a139867 --- /dev/null +++ b/api/models/ResetPasswordForm.php @@ -0,0 +1,65 @@ +_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); + } +} diff --git a/api/models/SignupForm.php b/api/models/SignupForm.php new file mode 100644 index 0000000..94917eb --- /dev/null +++ b/api/models/SignupForm.php @@ -0,0 +1,59 @@ + '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; + } +} diff --git a/api/runtime/.gitignore b/api/runtime/.gitignore new file mode 100644 index 0000000..c96a04f --- /dev/null +++ b/api/runtime/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/api/views/layouts/main.php b/api/views/layouts/main.php new file mode 100644 index 0000000..0afb7ed --- /dev/null +++ b/api/views/layouts/main.php @@ -0,0 +1,77 @@ + +beginPage() ?> + + + + + + + <?= Html::encode($this->title) ?> + head() ?> + + +beginBody() ?> + +
+ '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(); + ?> + +
+ isset($this->params['breadcrumbs']) ? $this->params['breadcrumbs'] : [], + ]) ?> + +
+
+ + + +endBody() ?> + + +endPage() ?> diff --git a/api/views/site/about.php b/api/views/site/about.php new file mode 100644 index 0000000..8eb0764 --- /dev/null +++ b/api/views/site/about.php @@ -0,0 +1,16 @@ +title = 'About'; +$this->params['breadcrumbs'][] = $this->title; +?> +
+

title) ?>

+ +

This is the About page. You may modify the following file to customize its content:

+ + +
diff --git a/api/views/site/contact.php b/api/views/site/contact.php new file mode 100644 index 0000000..be11983 --- /dev/null +++ b/api/views/site/contact.php @@ -0,0 +1,45 @@ +title = 'Contact'; +$this->params['breadcrumbs'][] = $this->title; +?> +
+

title) ?>

+ +

+ If you have business inquiries or other questions, please fill out the following form to contact us. Thank you. +

+ +
+
+ 'contact-form']); ?> + + field($model, 'name') ?> + + field($model, 'email') ?> + + field($model, 'subject') ?> + + field($model, 'body')->textArea(['rows' => 6]) ?> + + field($model, 'verifyCode')->widget(Captcha::className(), [ + 'template' => '
{image}
{input}
', + ]) ?> + +
+ 'btn btn-primary', 'name' => 'contact-button']) ?> +
+ + +
+
+ +
diff --git a/api/views/site/error.php b/api/views/site/error.php new file mode 100644 index 0000000..0ba2574 --- /dev/null +++ b/api/views/site/error.php @@ -0,0 +1,27 @@ +title = $name; +?> +
+ +

title) ?>

+ +
+ +
+ +

+ The above error occurred while the Web server was processing your request. +

+

+ Please contact us if you think this is a server error. Thank you. +

+ +
diff --git a/api/views/site/index.php b/api/views/site/index.php new file mode 100644 index 0000000..f780610 --- /dev/null +++ b/api/views/site/index.php @@ -0,0 +1,53 @@ +title = 'My Yii Application'; +?> +
+ +
+

Congratulations!

+ +

You have successfully created your Yii-powered application.

+ +

Get started with Yii

+
+ +
+ +
+
+

Heading

+ +

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.

+ +

Yii Documentation »

+
+
+

Heading

+ +

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.

+ +

Yii Forum »

+
+
+

Heading

+ +

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.

+ +

Yii Extensions »

+
+
+ +
+
diff --git a/api/views/site/login.php b/api/views/site/login.php new file mode 100644 index 0000000..fe67ee0 --- /dev/null +++ b/api/views/site/login.php @@ -0,0 +1,39 @@ +title = 'Login'; +$this->params['breadcrumbs'][] = $this->title; +?> +
+

title) ?>

+ +

Please fill out the following fields to login:

+ +
+
+ 'login-form']); ?> + + field($model, 'username') ?> + + field($model, 'password')->passwordInput() ?> + + field($model, 'rememberMe')->checkbox() ?> + +
+ If you forgot your password you can . +
+ +
+ 'btn btn-primary', 'name' => 'login-button']) ?> +
+ + +
+
+
diff --git a/api/views/site/requestPasswordResetToken.php b/api/views/site/requestPasswordResetToken.php new file mode 100644 index 0000000..a687530 --- /dev/null +++ b/api/views/site/requestPasswordResetToken.php @@ -0,0 +1,31 @@ +title = 'Request password reset'; +$this->params['breadcrumbs'][] = $this->title; +?> +
+

title) ?>

+ +

Please fill out your email. A link to reset password will be sent there.

+ +
+
+ 'request-password-reset-form']); ?> + + field($model, 'email') ?> + +
+ 'btn btn-primary']) ?> +
+ + +
+
+
diff --git a/api/views/site/resetPassword.php b/api/views/site/resetPassword.php new file mode 100644 index 0000000..6818ca9 --- /dev/null +++ b/api/views/site/resetPassword.php @@ -0,0 +1,31 @@ +title = 'Reset password'; +$this->params['breadcrumbs'][] = $this->title; +?> +
+

title) ?>

+ +

Please choose your new password:

+ +
+
+ 'reset-password-form']); ?> + + field($model, 'password')->passwordInput() ?> + +
+ 'btn btn-primary']) ?> +
+ + +
+
+
diff --git a/api/views/site/signup.php b/api/views/site/signup.php new file mode 100644 index 0000000..bbaffc5 --- /dev/null +++ b/api/views/site/signup.php @@ -0,0 +1,35 @@ +title = 'Signup'; +$this->params['breadcrumbs'][] = $this->title; +?> +
+

title) ?>

+ +

Please fill out the following fields to signup:

+ +
+
+ 'form-signup']); ?> + + field($model, 'username') ?> + + field($model, 'email') ?> + + field($model, 'password')->passwordInput() ?> + +
+ 'btn btn-primary', 'name' => 'signup-button']) ?> +
+ + +
+
+
diff --git a/api/web/.gitignore b/api/web/.gitignore new file mode 100644 index 0000000..25c74e6 --- /dev/null +++ b/api/web/.gitignore @@ -0,0 +1,2 @@ +/index.php +/index-test.php diff --git a/api/web/assets/.gitignore b/api/web/assets/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/api/web/assets/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/api/web/favicon.ico b/api/web/favicon.ico new file mode 100644 index 0000000..580ed73 Binary files /dev/null and b/api/web/favicon.ico differ diff --git a/api/web/robots.txt b/api/web/robots.txt new file mode 100644 index 0000000..6f27bb6 --- /dev/null +++ b/api/web/robots.txt @@ -0,0 +1,2 @@ +User-agent: * +Disallow: \ No newline at end of file diff --git a/common/config/.gitignore b/common/config/.gitignore new file mode 100644 index 0000000..97c0f01 --- /dev/null +++ b/common/config/.gitignore @@ -0,0 +1,2 @@ +main-local.php +params-local.php diff --git a/common/config/bootstrap.php b/common/config/bootstrap.php new file mode 100644 index 0000000..892906d --- /dev/null +++ b/common/config/bootstrap.php @@ -0,0 +1,4 @@ + 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', + ], + ], +]; diff --git a/common/config/params.php b/common/config/params.php new file mode 100644 index 0000000..4ec9ba6 --- /dev/null +++ b/common/config/params.php @@ -0,0 +1,6 @@ + 'admin@example.com', + 'supportEmail' => 'support@example.com', + 'user.passwordResetTokenExpire' => 3600, +]; diff --git a/common/mail/layouts/html.php b/common/mail/layouts/html.php new file mode 100644 index 0000000..bddbc61 --- /dev/null +++ b/common/mail/layouts/html.php @@ -0,0 +1,22 @@ + +beginPage() ?> + + + + + <?= Html::encode($this->title) ?> + head() ?> + + + beginBody() ?> + + endBody() ?> + + +endPage() ?> diff --git a/common/mail/layouts/text.php b/common/mail/layouts/text.php new file mode 100644 index 0000000..7087cea --- /dev/null +++ b/common/mail/layouts/text.php @@ -0,0 +1,12 @@ + +beginPage() ?> +beginBody() ?> + +endBody() ?> +endPage() ?> diff --git a/common/mail/passwordResetToken-html.php b/common/mail/passwordResetToken-html.php new file mode 100644 index 0000000..f3daf49 --- /dev/null +++ b/common/mail/passwordResetToken-html.php @@ -0,0 +1,15 @@ +urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]); +?> +
+

Hello username) ?>,

+ +

Follow the link below to reset your password:

+ +

+
diff --git a/common/mail/passwordResetToken-text.php b/common/mail/passwordResetToken-text.php new file mode 100644 index 0000000..244c0cb --- /dev/null +++ b/common/mail/passwordResetToken-text.php @@ -0,0 +1,12 @@ +urlManager->createAbsoluteUrl(['site/reset-password', 'token' => $user->password_reset_token]); +?> +Hello username ?>, + +Follow the link below to reset your password: + + diff --git a/common/models/LoginForm.php b/common/models/LoginForm.php new file mode 100644 index 0000000..afc1c23 --- /dev/null +++ b/common/models/LoginForm.php @@ -0,0 +1,78 @@ +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; + } +} diff --git a/common/models/User.php b/common/models/User.php new file mode 100644 index 0000000..ce78fcd --- /dev/null +++ b/common/models/User.php @@ -0,0 +1,188 @@ + 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; + } +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..22993b0 --- /dev/null +++ b/composer.json @@ -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" + } + } +} diff --git a/console/config/.gitignore b/console/config/.gitignore new file mode 100644 index 0000000..20da318 --- /dev/null +++ b/console/config/.gitignore @@ -0,0 +1,2 @@ +main-local.php +params-local.php \ No newline at end of file diff --git a/console/config/bootstrap.php b/console/config/bootstrap.php new file mode 100644 index 0000000..b3d9bbc --- /dev/null +++ b/console/config/bootstrap.php @@ -0,0 +1 @@ + 'app-console', + 'basePath' => dirname(__DIR__), + 'bootstrap' => ['log'], + 'controllerNamespace' => 'console\controllers', + 'components' => [ + 'log' => [ + 'targets' => [ + [ + 'class' => 'yii\log\FileTarget', + 'levels' => ['error', 'warning'], + ], + ], + ], + ], + 'params' => $params, +]; diff --git a/console/config/params.php b/console/config/params.php new file mode 100644 index 0000000..7f754b9 --- /dev/null +++ b/console/config/params.php @@ -0,0 +1,4 @@ + 'admin@example.com', +]; diff --git a/console/controllers/.gitkeep b/console/controllers/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/console/migrations/m130524_201442_init.php b/console/migrations/m130524_201442_init.php new file mode 100644 index 0000000..81a322a --- /dev/null +++ b/console/migrations/m130524_201442_init.php @@ -0,0 +1,34 @@ +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}}'); + } +} diff --git a/console/models/.gitkeep b/console/models/.gitkeep new file mode 100644 index 0000000..72e8ffc --- /dev/null +++ b/console/models/.gitkeep @@ -0,0 +1 @@ +* diff --git a/console/runtime/.gitignore b/console/runtime/.gitignore new file mode 100644 index 0000000..c96a04f --- /dev/null +++ b/console/runtime/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore \ No newline at end of file diff --git a/environments/dev/api/config/main-local.php b/environments/dev/api/config/main-local.php new file mode 100644 index 0000000..d9e3809 --- /dev/null +++ b/environments/dev/api/config/main-local.php @@ -0,0 +1,21 @@ + [ + '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; diff --git a/environments/dev/api/config/params-local.php b/environments/dev/api/config/params-local.php new file mode 100644 index 0000000..d0b9c34 --- /dev/null +++ b/environments/dev/api/config/params-local.php @@ -0,0 +1,3 @@ +run(); diff --git a/environments/dev/api/web/index.php b/environments/dev/api/web/index.php new file mode 100644 index 0000000..6038167 --- /dev/null +++ b/environments/dev/api/web/index.php @@ -0,0 +1,18 @@ +run(); diff --git a/environments/dev/common/config/main-local.php b/environments/dev/common/config/main-local.php new file mode 100644 index 0000000..8f3311c --- /dev/null +++ b/environments/dev/common/config/main-local.php @@ -0,0 +1,16 @@ + [ + '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, + ], + ], +]; diff --git a/environments/dev/common/config/params-local.php b/environments/dev/common/config/params-local.php new file mode 100644 index 0000000..d0b9c34 --- /dev/null +++ b/environments/dev/common/config/params-local.php @@ -0,0 +1,3 @@ + ['gii'], + 'modules' => [ + 'gii' => 'yii\gii\Module', + ], +]; diff --git a/environments/dev/console/config/params-local.php b/environments/dev/console/config/params-local.php new file mode 100644 index 0000000..d0b9c34 --- /dev/null +++ b/environments/dev/console/config/params-local.php @@ -0,0 +1,3 @@ +run(); +exit($exitCode); diff --git a/environments/index.php b/environments/index.php new file mode 100644 index 0000000..3fe42a0 --- /dev/null +++ b/environments/index.php @@ -0,0 +1,59 @@ + [ + * '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', + ], + ], +]; diff --git a/environments/prod/common/config/main-local.php b/environments/prod/common/config/main-local.php new file mode 100644 index 0000000..e4e6d99 --- /dev/null +++ b/environments/prod/common/config/main-local.php @@ -0,0 +1,10 @@ + [ + 'db' => [ + 'dsn' => 'mysql:host=localhost;dbname=ely_accounts', + 'username' => 'root', + 'password' => '', + ], + ], +]; diff --git a/environments/prod/common/config/params-local.php b/environments/prod/common/config/params-local.php new file mode 100644 index 0000000..d0b9c34 --- /dev/null +++ b/environments/prod/common/config/params-local.php @@ -0,0 +1,3 @@ +run(); +exit($exitCode); diff --git a/init b/init new file mode 100644 index 0000000..1b35927 --- /dev/null +++ b/init @@ -0,0 +1,209 @@ +#!/usr/bin/env php + + * + * @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); + } +} diff --git a/init.bat b/init.bat new file mode 100644 index 0000000..e50c242 --- /dev/null +++ b/init.bat @@ -0,0 +1,20 @@ +@echo off + +rem ------------------------------------------------------------- +rem Yii command line init script for Windows. +rem +rem @author Qiang Xue +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 diff --git a/tests/README.md b/tests/README.md new file mode 100644 index 0000000..ad7f016 --- /dev/null +++ b/tests/README.md @@ -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 + ``` + + Then add `/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`. diff --git a/tests/codeception.yml b/tests/codeception.yml new file mode 100644 index 0000000..d6db419 --- /dev/null +++ b/tests/codeception.yml @@ -0,0 +1,10 @@ +include: + - codeception/common + - codeception/console + - codeception/api + +paths: + log: codeception/_output + +settings: + colors: true diff --git a/tests/codeception/_output/.gitignore b/tests/codeception/_output/.gitignore new file mode 100644 index 0000000..d6b7ef3 --- /dev/null +++ b/tests/codeception/_output/.gitignore @@ -0,0 +1,2 @@ +* +!.gitignore diff --git a/tests/codeception/api/.gitignore b/tests/codeception/api/.gitignore new file mode 100644 index 0000000..985dbb4 --- /dev/null +++ b/tests/codeception/api/.gitignore @@ -0,0 +1,4 @@ +# these files are auto generated by codeception build +/unit/UnitTester.php +/functional/FunctionalTester.php +/acceptance/AcceptanceTester.php diff --git a/tests/codeception/api/_bootstrap.php b/tests/codeception/api/_bootstrap.php new file mode 100644 index 0000000..0dcc5b6 --- /dev/null +++ b/tests/codeception/api/_bootstrap.php @@ -0,0 +1,23 @@ + $value) { + $inputType = $field === 'body' ? 'textarea' : 'input'; + $this->actor->fillField($inputType . '[name="ContactForm[' . $field . ']"]', $value); + } + $this->actor->click('contact-button'); + } +} diff --git a/tests/codeception/api/_pages/SignupPage.php b/tests/codeception/api/_pages/SignupPage.php new file mode 100644 index 0000000..bfae9ab --- /dev/null +++ b/tests/codeception/api/_pages/SignupPage.php @@ -0,0 +1,27 @@ + $value) { + $inputType = $field === 'body' ? 'textarea' : 'input'; + $this->actor->fillField($inputType . '[name="SignupForm[' . $field . ']"]', $value); + } + $this->actor->click('signup-button'); + } +} diff --git a/tests/codeception/api/acceptance.suite.yml b/tests/codeception/api/acceptance.suite.yml new file mode 100644 index 0000000..1828a04 --- /dev/null +++ b/tests/codeception/api/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: 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 diff --git a/tests/codeception/api/acceptance/AboutCept.php b/tests/codeception/api/acceptance/AboutCept.php new file mode 100644 index 0000000..c25ae81 --- /dev/null +++ b/tests/codeception/api/acceptance/AboutCept.php @@ -0,0 +1,10 @@ +wantTo('ensure that about works'); +AboutPage::openBy($I); +$I->see('About', 'h1'); diff --git a/tests/codeception/api/acceptance/ContactCept.php b/tests/codeception/api/acceptance/ContactCept.php new file mode 100644 index 0000000..16bdd31 --- /dev/null +++ b/tests/codeception/api/acceptance/ContactCept.php @@ -0,0 +1,56 @@ +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.'); diff --git a/tests/codeception/api/acceptance/HomeCept.php b/tests/codeception/api/acceptance/HomeCept.php new file mode 100644 index 0000000..c05212f --- /dev/null +++ b/tests/codeception/api/acceptance/HomeCept.php @@ -0,0 +1,12 @@ +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/tests/codeception/api/acceptance/LoginCept.php b/tests/codeception/api/acceptance/LoginCept.php new file mode 100644 index 0000000..21f3148 --- /dev/null +++ b/tests/codeception/api/acceptance/LoginCept.php @@ -0,0 +1,34 @@ +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'); + */ diff --git a/tests/codeception/api/acceptance/SignupCest.php b/tests/codeception/api/acceptance/SignupCest.php new file mode 100644 index 0000000..96822f6 --- /dev/null +++ b/tests/codeception/api/acceptance/SignupCest.php @@ -0,0 +1,82 @@ + '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)'); + } +} diff --git a/tests/codeception/api/acceptance/_bootstrap.php b/tests/codeception/api/acceptance/_bootstrap.php new file mode 100644 index 0000000..11437fe --- /dev/null +++ b/tests/codeception/api/acceptance/_bootstrap.php @@ -0,0 +1,2 @@ +wantTo('ensure that about works'); +AboutPage::openBy($I); +$I->see('About', 'h1'); diff --git a/tests/codeception/api/functional/ContactCept.php b/tests/codeception/api/functional/ContactCept.php new file mode 100644 index 0000000..1558ea4 --- /dev/null +++ b/tests/codeception/api/functional/ContactCept.php @@ -0,0 +1,47 @@ +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.'); diff --git a/tests/codeception/api/functional/HomeCept.php b/tests/codeception/api/functional/HomeCept.php new file mode 100644 index 0000000..68059b0 --- /dev/null +++ b/tests/codeception/api/functional/HomeCept.php @@ -0,0 +1,12 @@ +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/tests/codeception/api/functional/LoginCept.php b/tests/codeception/api/functional/LoginCept.php new file mode 100644 index 0000000..79afe51 --- /dev/null +++ b/tests/codeception/api/functional/LoginCept.php @@ -0,0 +1,29 @@ +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'); diff --git a/tests/codeception/api/functional/SignupCest.php b/tests/codeception/api/functional/SignupCest.php new file mode 100644 index 0000000..498c1ae --- /dev/null +++ b/tests/codeception/api/functional/SignupCest.php @@ -0,0 +1,90 @@ + '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)'); + } +} diff --git a/tests/codeception/api/functional/_bootstrap.php b/tests/codeception/api/functional/_bootstrap.php new file mode 100644 index 0000000..b89a993 --- /dev/null +++ b/tests/codeception/api/functional/_bootstrap.php @@ -0,0 +1,3 @@ + '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', + ], +]; diff --git a/tests/codeception/api/unit/models/ContactFormTest.php b/tests/codeception/api/unit/models/ContactFormTest.php new file mode 100644 index 0000000..775a553 --- /dev/null +++ b/tests/codeception/api/unit/models/ContactFormTest.php @@ -0,0 +1,59 @@ +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'; + } +} diff --git a/tests/codeception/api/unit/models/PasswordResetRequestFormTest.php b/tests/codeception/api/unit/models/PasswordResetRequestFormTest.php new file mode 100644 index 0000000..776f19b --- /dev/null +++ b/tests/codeception/api/unit/models/PasswordResetRequestFormTest.php @@ -0,0 +1,87 @@ +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'; + } +} diff --git a/tests/codeception/api/unit/models/ResetPasswordFormTest.php b/tests/codeception/api/unit/models/ResetPasswordFormTest.php new file mode 100644 index 0000000..b3ab142 --- /dev/null +++ b/tests/codeception/api/unit/models/ResetPasswordFormTest.php @@ -0,0 +1,43 @@ +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' + ], + ]; + } +} diff --git a/tests/codeception/api/unit/models/SignupFormTest.php b/tests/codeception/api/unit/models/SignupFormTest.php new file mode 100644 index 0000000..e06a46c --- /dev/null +++ b/tests/codeception/api/unit/models/SignupFormTest.php @@ -0,0 +1,52 @@ + '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', + ], + ]; + } +} diff --git a/tests/codeception/bin/_bootstrap.php b/tests/codeception/bin/_bootstrap.php new file mode 100644 index 0000000..f1fbb72 --- /dev/null +++ b/tests/codeception/bin/_bootstrap.php @@ -0,0 +1,19 @@ +run(); +exit($exitCode); diff --git a/tests/codeception/bin/yii.bat b/tests/codeception/bin/yii.bat new file mode 100644 index 0000000..d516b3a --- /dev/null +++ b/tests/codeception/bin/yii.bat @@ -0,0 +1,20 @@ +@echo off + +rem ------------------------------------------------------------- +rem Yii command line bootstrap script for Windows. +rem +rem @author Qiang Xue +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 diff --git a/tests/codeception/common/.gitignore b/tests/codeception/common/.gitignore new file mode 100644 index 0000000..985dbb4 --- /dev/null +++ b/tests/codeception/common/.gitignore @@ -0,0 +1,4 @@ +# these files are auto generated by codeception build +/unit/UnitTester.php +/functional/FunctionalTester.php +/acceptance/AcceptanceTester.php diff --git a/tests/codeception/common/_bootstrap.php b/tests/codeception/common/_bootstrap.php new file mode 100644 index 0000000..cea3ee5 --- /dev/null +++ b/tests/codeception/common/_bootstrap.php @@ -0,0 +1,15 @@ +actor->fillField('input[name="LoginForm[username]"]', $username); + $this->actor->fillField('input[name="LoginForm[password]"]', $password); + $this->actor->click('login-button'); + } +} diff --git a/tests/codeception/common/_support/FixtureHelper.php b/tests/codeception/common/_support/FixtureHelper.php new file mode 100644 index 0000000..c5ebcf1 --- /dev/null +++ b/tests/codeception/common/_support/FixtureHelper.php @@ -0,0 +1,72 @@ +loadFixtures(); + } + + /** + * Method is called after all suite tests run + */ + public function _afterSuite() + { + $this->unloadFixtures(); + } + + /** + * @inheritdoc + */ + public function globalFixtures() + { + return [ + InitDbFixture::className(), + ]; + } + + /** + * @inheritdoc + */ + public function fixtures() + { + return [ + 'user' => [ + 'class' => UserFixture::className(), + 'dataFile' => '@tests/codeception/common/fixtures/data/init_login.php', + ], + ]; + } +} diff --git a/tests/codeception/common/codeception.yml b/tests/codeception/common/codeception.yml new file mode 100644 index 0000000..e8a3407 --- /dev/null +++ b/tests/codeception/common/codeception.yml @@ -0,0 +1,13 @@ +namespace: tests\codeception\common +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 diff --git a/tests/codeception/common/fixtures/UserFixture.php b/tests/codeception/common/fixtures/UserFixture.php new file mode 100644 index 0000000..7153c8c --- /dev/null +++ b/tests/codeception/common/fixtures/UserFixture.php @@ -0,0 +1,13 @@ + 'erau', + 'auth_key' => 'tUu1qHcde0diwUol3xeI-18MuHkkprQI', + // password_0 + 'password_hash' => '$2y$13$nJ1WDlBaGcbCdbNC5.5l4.sgy.OMEKCqtDQOdQ2OWpgiKRWYyzzne', + 'password_reset_token' => 'RkD_Jw0_8HEedzLk7MM-ZKEFfYR7VbMr_1392559490', + 'created_at' => '1392559490', + 'updated_at' => '1392559490', + 'email' => 'sfriesen@jenkins.info', + ], +]; diff --git a/tests/codeception/common/templates/fixtures/user.php b/tests/codeception/common/templates/fixtures/user.php new file mode 100644 index 0000000..d3f83b5 --- /dev/null +++ b/tests/codeception/common/templates/fixtures/user.php @@ -0,0 +1,17 @@ +getSecurity(); + +return [ + 'username' => $faker->userName, + 'email' => $faker->email, + 'auth_key' => $security->generateRandomString(), + 'password_hash' => $security->generatePasswordHash('password_' . $index), + 'password_reset_token' => $security->generateRandomString() . '_' . time(), + 'created_at' => time(), + 'updated_at' => time(), +]; diff --git a/tests/codeception/common/unit.suite.yml b/tests/codeception/common/unit.suite.yml new file mode 100644 index 0000000..a0582a5 --- /dev/null +++ b/tests/codeception/common/unit.suite.yml @@ -0,0 +1,6 @@ +# Codeception Test Suite Configuration + +# suite for unit (internal) tests. +# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES. + +class_name: UnitTester diff --git a/tests/codeception/common/unit/DbTestCase.php b/tests/codeception/common/unit/DbTestCase.php new file mode 100644 index 0000000..2159a69 --- /dev/null +++ b/tests/codeception/common/unit/DbTestCase.php @@ -0,0 +1,11 @@ + 'bayer.hudson', + 'auth_key' => 'HP187Mvq7Mmm3CTU80dLkGmni_FUH_lR', + //password_0 + 'password_hash' => '$2y$13$EjaPFBnZOQsHdGuHI.xvhuDp1fHpo8hKRSk6yshqa9c5EG8s3C3lO', + 'password_reset_token' => 'ExzkCOaYc1L8IOBs4wdTGGbgNiG3Wz1I_1402312317', + 'created_at' => '1402312317', + 'updated_at' => '1402312317', + 'email' => 'nicole.paucek@schultz.info', + ], +]; diff --git a/tests/codeception/common/unit/models/LoginFormTest.php b/tests/codeception/common/unit/models/LoginFormTest.php new file mode 100644 index 0000000..54c8209 --- /dev/null +++ b/tests/codeception/common/unit/models/LoginFormTest.php @@ -0,0 +1,93 @@ + [ + 'user' => [ + 'class' => 'yii\web\User', + 'identityClass' => 'common\models\User', + ], + ], + ]); + } + + protected function tearDown() + { + Yii::$app->user->logout(); + parent::tearDown(); + } + + public function testLoginNoUser() + { + $model = new LoginForm([ + 'username' => 'not_existing_username', + 'password' => 'not_existing_password', + ]); + + $this->specify('user should not be able to login, when there is no identity', function () use ($model) { + expect('model should not login user', $model->login())->false(); + expect('user should not be logged in', Yii::$app->user->isGuest)->true(); + }); + } + + public function testLoginWrongPassword() + { + $model = new LoginForm([ + 'username' => 'bayer.hudson', + 'password' => 'wrong_password', + ]); + + $this->specify('user should not be able to login with wrong password', function () use ($model) { + expect('model should not login user', $model->login())->false(); + expect('error message should be set', $model->errors)->hasKey('password'); + expect('user should not be logged in', Yii::$app->user->isGuest)->true(); + }); + } + + public function testLoginCorrect() + { + + $model = new LoginForm([ + 'username' => 'bayer.hudson', + 'password' => 'password_0', + ]); + + $this->specify('user should be able to login with correct credentials', function () use ($model) { + expect('model should login user', $model->login())->true(); + expect('error message should not be set', $model->errors)->hasntKey('password'); + expect('user should be logged in', Yii::$app->user->isGuest)->false(); + }); + } + + /** + * @inheritdoc + */ + public function fixtures() + { + return [ + 'user' => [ + 'class' => UserFixture::className(), + 'dataFile' => '@tests/codeception/common/unit/fixtures/data/models/user.php' + ], + ]; + } +} diff --git a/tests/codeception/config/acceptance.php b/tests/codeception/config/acceptance.php new file mode 100644 index 0000000..9318da5 --- /dev/null +++ b/tests/codeception/config/acceptance.php @@ -0,0 +1,7 @@ + 'app-common', + 'basePath' => dirname(__DIR__), + ] +); diff --git a/tests/codeception/config/config.php b/tests/codeception/config/config.php new file mode 100644 index 0000000..b478679 --- /dev/null +++ b/tests/codeception/config/config.php @@ -0,0 +1,26 @@ + 'en-US', + 'controllerMap' => [ + 'fixture' => [ + 'class' => 'yii\faker\FixtureController', + 'fixtureDataPath' => '@tests/codeception/common/fixtures/data', + 'templatePath' => '@tests/codeception/common/templates/fixtures', + 'namespace' => 'tests\codeception\common\fixtures', + ], + ], + 'components' => [ + 'db' => [ + 'dsn' => 'mysql:host=localhost;dbname=yii2_advanced_tests', + ], + 'mailer' => [ + 'useFileTransport' => true, + ], + 'urlManager' => [ + 'showScriptName' => true, + ], + ], +]; diff --git a/tests/codeception/config/console/unit.php b/tests/codeception/config/console/unit.php new file mode 100644 index 0000000..4d3aeb0 --- /dev/null +++ b/tests/codeception/config/console/unit.php @@ -0,0 +1,14 @@ + [ + 'request' => [ + // it's not recommended to run functional tests with CSRF validation enabled + 'enableCsrfValidation' => false, + // but if you absolutely need it set cookie domain to localhost + /* + 'csrfCookie' => [ + 'domain' => 'localhost', + ], + */ + ], + ], +]; \ No newline at end of file diff --git a/tests/codeception/config/unit.php b/tests/codeception/config/unit.php new file mode 100644 index 0000000..6bd08d3 --- /dev/null +++ b/tests/codeception/config/unit.php @@ -0,0 +1,7 @@ + +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