Call to undefined function tests\codeception\unit\models\expect() - yii2

I am trying to perform unit testing using the default ContactFormTest inside the yii2 basic application. But it provides me the following error.
E:\xampp\htdocs\news\tests>codecept run unit codeception\unit\models\ContactForm
Test.php
Codeception PHP Testing Framework v2.0.16
Powered by PHPUnit 4.7.7 by Sebastian Bergmann and contributors.
←[1mUnit Tests (1) ←[22m--------------------------------------------------------
------------------------------------
←[35;1mTest contact←[39;22m (tests\codeception\unit\models\ContactFormTest::test
Contact)<pre>PHP Fatal Error 'yii\base\ErrorException' with message &#
039;Call to undefined function tests\codeception\unit\models\expect()'
in E:\xampp\htdocs\news\tests\codeception\unit\models\ContactFormTest.php:46
Stack trace:
#0 [internal function]: yii\base\ErrorHandler->handleFatalError()
#1 {main}</pre>
Below is my ContactFormTest.php
namespace tests\codeception\unit\models;
use app\models\ContactForm;
use Yii;
use yii\codeception\TestCase;
use Codeception\Specify;
use Codeception\Util\Debug;
class ContactFormTest extends TestCase
{
use Specify;
protected function setUp()
{
parent::setUp();
Yii::$app->mailer->fileTransportCallback = function ($mailer, $message) {
return 'testing_message.eml';
};
}
protected function tearDown()
{
unlink($this->getMessageFile());
parent::tearDown();
}
public function testContact()
{
/** #var ContactForm $model */
$model = $this->getMockBuilder('app\models\ContactForm')
->setMethods(['validate'])
->getMock();
$model->expects($this->once())->method('validate')->will($this->returnValue(true));
$model->attributes = [
'name' => 'Tester',
'email' => 'tester#example.com',
'subject' => 'very important letter subject',
'body' => 'body of current message',
];
//Debug::debug($model->contact('admin#example.com'));
//die();
$this->specify('email should be send', function () use ($model) {
expect('ContactForm::contact() should return true', $model->contact('admin#example.com'))->true(); //this throws the error
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';
}
}
And unit.suite.yml
# Codeception Test Suite Configuration
# suite for unit (internal) tests.
# RUN `build` COMMAND AFTER ADDING/REMOVING MODULES.
class_name: UnitTester
modules:
config:
Db:
dsn: 'mysql:host=127.0.0.1;dbname=news_tests'
user: 'root'
password: ''
dump: 'tests/_data/dump.sql'
populate: false
cleanup: false
reconnect: true
How to fix this?

Does your IDE recognize the expect function calls inside specify?
If not, then try adding specify and verify to require-dev Composer dependencies as specified in the manual:
"require-dev": {
...
"codeception/specify": "*",
"codeception/verify": "*"
}
And run composer update.
P.S. link with credit for Russian-speaking readers.

Related

laravel 5.6 with MySql gives Symfony \ Component \ HttpKernel \ Exception \ MethodNotAllowedHttpException error

There are similar questions under this topic, but none of them gave me an answer. I'm a beginner to laravel and trying to learn by myself.
When I try to connect laravel (version 5.6) with MySql it gives this error.
These are the code lines that working with.
CameraController.php
<?php
namespace App\Http\Controllers;
use App\Camera;
use Illuminate\Http\Request;
class CameraController extends Controller{
public function postCamera(Request $request){
$camera = new Camera();
$camera->email = $request->input('email');
$camera->password = $request->input('password');
$camera->save();
return response()->json([
'message'=>$camera
]);
}
}
CreateCamreasTable.php
public function up(){
Schema::create('cameras', function (Blueprint $table) {
$table->increments('id');
$table->timestamps();
$table->text('email');
$table->text('password');
});
}
api.php
Route::post('/addCamera', ['as' => 'Camera', 'uses' => 'CameraController#postCamera']);
user.php
class User extends Authenticatable{
use Notifiable;
protected $fillable = [
'email',
];
protected $hidden = [
'password',
];
}
I couldn't found out what's wrong with my code..
PS- I'm trying with postman app that supports with sending requests and reading responses. what I'm sending is a json object
{
"email" : "rr#gmal.com",
"password" : "fjf"
}
The error that I receive is

LDAP with Guard Authentication System in Symfony 3

What I'm pretending to do is to include the LDAP for internal users in a Guard Authentication System configured by ddbb.
I already have build my Guard Authentication System and works really nice thanks to https://knpuniversity.com/screencast/symfony-security.
But I need also to try to log in previously via LDAP mode. More precisely, the functionality must be like this:
The user try to log in on the Guard System Authentication configured with a database from MySQL and:
1- Check if exist the user in the table User from MySQL. If exist, we go to step 2. If not exist return false to the authentication with the error message.
2-Check if the user exist in the LDAP mode. If exist go to the step 3. If not exist go to the step 4.
3-Try to log in via LDAP with the username and password. If the authentication is ok, it's logged in. If can't match the password via LDAP, return false to the authentication with the error message.
4-After checking the LDAP option, we will just try to log in via Guard Authentication System. If the authentication it's ok, the user is logged in. If can't match the password via Guard with the MySQL users table, return false to the authentication with the error message.
In the LoginFormAuthenticator file I finally could manage this behavior I want as shows the next code.
<?php
namespace AppBundle\Security;
use ...
use Zend\Ldap\Ldap;
use Zend\Ldap\Exception\LdapException;
class LoginFormAuthenticator extends AbstractFormLoginAuthenticator
{
use TargetPathTrait;
private $em;
private $router;
private $passwordEncoder;
private $csrfTokenManager;
public function __construct(...
}
public function getCredentials(Request $request)
{
...
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$username = $credentials['username'];
$ldapPassword = $credentials['password'];
$ldaphost = 'ldap.example.com'; // your ldap servers
$baseDn = 'dc=example,dc=es';
$options = [
'host' => $ldaphost,
'username' => $username,
'password' => $ldapPassword,
'bindRequiresDn' => false,
'accountDomainName' => 'example.es',
'baseDn' => $baseDn,
];
$userInterface = $this->em->getRepository('AppBundle:User')
->findOneBy(['email' => $username]);
$ldap = new Ldap($options);
try {
$ldap->bind();
$userInterface->setIsAuthenticationLDAP(true);
} catch (LdapException $zle){
$userInterface->setIsAuthenticationLDAP(false);
}
return $userInterface;
}
public function checkCredentials($credentials, UserInterface $user)
{
$password = $credentials['password'];
if($user->isAuthenticationLDAP()){
$user->setLoginAttempts(0);
$this->em->persist($user);
$this->em->flush();
return true;
} else {
if($this->passwordEncoder->isPasswordValid($user, $password)) {
$user->setLoginAttempts(0);
$this->em->persist($user);
$this->em->flush();
return true;
} else {
if($user->getLoginAttempts() == '0') $user->setFirstLoginAttempt(new \DateTime('now'));
$user->setLoginAttempts($user->getLoginAttempts() + 1);
if($user->getLoginAttempts() >= 5) {
$user->setLockedDateTime(new \DateTime('now'));
$user->setLoginAttempts(0);
}
$this->em->persist($user);
$this->em->flush();
}
}
return false;
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
....
}
protected function getLoginUrl()
{
return $this->router->generate('fos_user_security_login');
}
}
I hope anyone can enjoy this answer.

Can I have a ZF3 MVC Framework Controller with parameters in the constructor?

I have a Zend Framework 3 MVC app with a controller with two end points. Both need to access the same class. It seems like the best way to do this would be to would be to make an instance of this class a property of the controller class like this:
class IndexController extends AbstractActionController
{
/**
* var Utility $utility
*/
protected $utility;
public function __construct(Utility $utility)
{
$this->utility = $utility;
}
public function indexAction()
{
$this->utility->doA('param1');
return new ViewModel();
}
public function otherAction()
{
$results = $this->utility->validateRequest($this->request);
if ($results)
{
return new ViewModel();
}
else
{
throw new Exception('Invalid request');
}
}
}
However, I don't know how to pass paramaters to the constructor since I don't know where Zend Framework "makes" it.
Zend Framework uses a concept called Dependency Injection. This is based on the D in SOLID, dependency inversion. Theory aside, you need to make a custom factory for your controller in modules.config.php. You also need to make a factory for the class calld Utility.
So first of all, you probably made your project with a command similar to composer create-project -sdev zendframework/skeleton-application. If you did that you probably don't have the latest version of Service Manager. See if the file vendor/bin/generate-factory-for-class exists. If not, execute composer update zendframework/zend-servicemanager to add it there.
Now lets make a factory for the utility class. Lets assume its in module/Application/src/Service/Utility.php and has the namespace Application\Service. You just type vendor/bin/generate-factory-for-class Application\\Service\\Utility > module/Application/src/Service/UtilityFactory.php. If you look in that file you can see:
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new Utility();
}
Now lets do the same for the controller with vendor/bin/generate-factory-for-class Application\\Controller\\IndexController > module/Application/src/Controller/IndexControllerFactory.php. Open this factory and see its a little more complex.
public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
{
return new IndexController($container->get(\Application\Service\Utility::class));
}
$container is your dependency injection container. It executes the __invoke command in these factories when called.
One more thing left to do. you need to edit your module.config.php. Replace the line
'controllers' => [
'factories' => [
Controller\IndexController::class => InvokableFactory::class,
],
],
with
'controllers' => [
'factories' => [
Controller\IndexController::class => Controller\IndexControllerFactory::class,
],
],
Now add the following section to the config:
'service_manager' => [
'factories' => [
Service\Utility::class => InvokableFactory::class,
],
],
Then your controller should work.

Laravel 5 PHPUnit test json post

I am trying to test a JSON API following the officiel doc. I know the problem comes from the data array given to the POST request. The test works fine with a single level array like ['hello' => 'world'], so apparently the post function cannot handle complex structures ? What am I doing wrong here ?
Test:
public function testInsert()
{
$this->post(
'/test',
[
'content' => 'Hello world!',
'count' => [
'a' => 12.345678,
'b' => 12.345678
],
'user' => [
'id' => 1
]
],
['contentType' => 'application/json']
)->seeJsonEquals([
'status' => true
]);
}
Error:
unknown:myapp nobody$ phpunit
PHPUnit 4.8.24 by Sebastian Bergmann and contributors.
E.
Time: 648 ms, Memory: 15.25Mb
There was 1 error:
1) APITest::testInsert
ErrorException: Invalid argument supplied for foreach()
/Users/nobody/myapp/vendor/laravel/framework/src/Illuminate/Support/Arr.php:487
/Users/nobody/myapp/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.php:231
/Users/nobody/myapp/tests/APITest.php:43
FAILURES!
Tests: 2, Assertions: 2, Errors: 1.
Controller:
public function store() {
$user = User::find(Input::get('user.id'));
// TODO: Validate input using JSON schema
if (empty($user))
$errors[] = 'User does not exist.';
if (empty(Input::get('content')))
$errors[] = 'Content is empty.';
$a = Input::get('location.latitude');
if ($a < 15)
$errors[] = 'A out of range.';
$b = Input::get('location.longitude');
if ($b < 20)
$errors[] = 'B out of range.';
if (empty($errors)) {
$post = new Post();
$post->content = Input::get('content');
$post->count()->create([
'a' => $a,
'b' => $b
]);
$user->posts()->save($user);
$post->save();
return APIUtils::makeStatusResponse(true);
}
return APIUtils::makeStatusResponse(false, $errors);
}
I re-installed my Laravel application using the laravel new myapp command and everything works fine now. I am assuming the problem was coming from the previous install made with composer create-project --prefer-dist laravel/laravel may.

Yii2 model custom rules and validations for attribute which is array

Being trying to sort this out but going nowhere with it. I have got an array as attribute for a model and I am trying to create custom validation for some of the keys in the array as required. Or even can't figure out how the attribute labels will work? Here is my code:
MODEL
...
public $company = [
'name' => '',
'trading_name' => '',
'type' => '',
];
public function attributeLabels(){
return [
'company[name]' => 'Company Name',
];
}
public function rules(){
return [
[['company[name]','company[trading_name'], 'safe'],
[['company[name]'], 'return_check','skipOnEmpty'=> false],
];
}
public function return_check($attribute, $params){
$this->addError($attribute ,'Required ');
return false;
}
...
I have even tried to pass the whole array and check in the validator method for the keys and values but the custom validator is not even triggered.
I think you need separated model for company.
I've used custom rule functions, and they all worked. Try removing the return clause at the end of the return_check function.
Here's what has worked for me:
class Essid extends ActiveRecord {
public function rules() {
return [
['network_name', 'checkNetworkName']
]
}
public function checkNetworkName($attribute, $params){
if (!$this->hasErrors()) {
if ( !ctype_alnum($this->network_name) )
$this->addError($attribute, Yii::t('app', 'Not a valid Network Name'));
}
}
}
Hope it helps