How to test cake3 plugins with fixtures - php

I'm having troubles trying to test a plugin using fixtures.
I've created the fixtures files under tests/Fixture with the structure as documentation:
namespace Files\Test\Fixture;
use Cake\TestSuite\Fixture\TestFixture;
/**
* FiledFixture
*
*/
class FiledFixture extends TestFixture {
/**
* Table name
*
* #var string
*/
public $table = 'filed';
/**
* Fields
*
* #var array
*/
public $fields = [
'id' => [
'type' => 'integer',
'length' => 11,
...
],
'foreign_key' => [
'type' => 'integer',
...
],
...
];
/**
* Records
*
* #var array
*/
public $records = [
[
'id' => 1,
'foreign_key' => 1,
'file_id' => 1,
'filedtype_id' => 1,
'model' => 'Lorem ipsum dolor sit amet',
'language' => 'Lore',
'created' => '2014-11-01 19:21:54',
'modified' => '2014-11-01 19:21:54'
],
];
}
And then in the TestCase i load the fixtures with the public variable fixtures:
<?php
namespace Files\Test\TestCase\Model\Table;
use Cake\ORM\TableRegistry;
use Files\Model\Table\FiledTable;
use Cake\TestSuite\TestCase;
/**
* Files\Model\Table\FiledTable Test Case
*/
class FiledTableTest extends TestCase {
/**
* Fixtures
*
* #var array
*/
public $fixtures = [
'plugin.files.filed',
'plugin.files.files',
'plugin.files.filedtypes',
'plugin.files.thumbs'
];
...
When I try to run phpunit I get the next error:
..Exception: Referenced fixture class "Files\Test\Fixture\FiledFixture" not found. Fixture "plugin.files.filed" was referenced in test case "Files\Test\TestCase\Model\Table\FiledTableTest". in [/home/genar/src/metropolitan-web-2015/vendor/cakephp/cakephp/src/TestSuite/Fixture/FixtureManager.php, line 180]
I tryed to create a custom bootstrap.php for testing but I cannot figure what has to be there. I copyed this one https://github.com/Xety/Cake3-Upload/blob/master/tests/bootstrap.php but it raises a lot of errors.
I've googled as well but I cannot find any information about testing on plugins, nor on the oficial documentation.
Any thoughts on how can I achieve this?

Well, finally I suposed the error was on the way composer autoloaders are generated. I've been looking how my Test\Fixture\ namespace was not added on autoload_psr4.php either running composer dump-autoload.
So the way I fixed this it was adding the right lines on composer.json of the plugin and running composer update to generate the autoloads well.
Note composer dump-autoload does not update your plugin psr4 routes when the plugin is intalled under vendors.

Related

What causes the 'Unknown format "factory"' error in this Laravel 8 app?

I am working on a Laravel 8 app with users and posts.
The objective is to create a bunch of posts (I already have users).
namespace Database\Factories;
// import Post model
use App\Models\Post;
// import User model
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class PostFactory extends Factory {
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = Post::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition() {
return [
'title' => $this->faker->sentence(3),
'description' => $this->faker->text,
'content' => $this->faker->paragraph,
'user_id' => $this->faker->factory(App\Models\User::class),
];
}
}
The problem
I run php artisan tinker then Post::factory()->count(100)->create() in the terminal and I get:
InvalidArgumentException with message 'Unknown format "factory"'
UPDATE
I replace my return statement with:
return [
'title' => $this->faker->sentence(3),
'description' => $this->faker->text,
'content' => $this->faker->paragraph,
'user_id' => User::factory(),
];
I get this in the terminal:
Class 'Database\Factories\UserFactory' not found
Questions:
Where is my mistake?
Does the fact that I get the error Class 'Database\Factories\UserFactory' not found mean that I need to
create a UserFactory factory? Because there isn't one. (I wanted
to create posts, not users).
I don't suppose there is $this->faker->factory(..).
You can do
'user_id' => App\Models\User::factory()->create()->id,
EDIT:
'user_id' => App\Models\User::factory(),
Creating a UserFactory factory and using the below return statement did the trick:
return [
'title' => $this->faker->sentence(3),
'description' => $this->faker->text,
'content' => $this->faker->paragraph,
'user_id' => User::factory(),
];
So, the PostFactory class looks like this:
class PostFactory extends Factory {
/**
* The name of the factory's corresponding model.
*
* #var string
*/
protected $model = Post::class;
/**
* Define the model's default state.
*
* #return array
*/
public function definition() {
return [
'title' => $this->faker->sentence(3),
'description' => $this->faker->text,
'content' => $this->faker->paragraph,
'user_id' => User::factory(),
];
}
}

Laravel Artisan event:generate command throwing a Fatal error

I'm following the official documentation for Laravel 5.7 on the events registration and generation: https://laravel.com/docs/5.7/events#generating-events-and-listeners
I have an EventServiceProvider with the following events defined:
<?php
namespace App\Providers;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event handler mappings for the application.
*
* #var array
*/
protected $listen = [
'App\Events\FormBeforeCreate' => [
'App\Listeners\WebhookBeforeCreate',
],
'App\Events\FormAfterCreate' => [
'App\Listeners\NotifyAfterCreate',
'App\Listeners\WebhookAfterCreate',
],
'App\Events\FormBeforeUpdate' => [
'App\Listeners\WebhookBeforeUpdate',
],
'App\Events\FormAfterUpdate' => [
'App\Listeners\NotifyAfterUpdate',
'App\Listeners\WebhookAfterUpdate',
],
'App\Events\FormBeforeDelete' => [
'App\Listeners\WebhookBeforeDelete',
],
'App\Events\FormAfterDelete' => [
'App\Listeners\NotifyAfterDelete',
'App\Listeners\WebhookAfterDelete',
],
'App\Events\FormBeforeSave' => [
'App\Listeners\WebhookBeforeSave',
],
'App\Events\FormAfterSave' => [
'App\Listeners\NotifyAfterSave',
'App\Listeners\WebhookAfterSave',
],
];
/**
* The subscriber classes to register.
*
* #var array
*/
protected $subscribe = [
'App\Listeners\UserEventSubscriber',
];
/**
* Register any other events for your application.
*
* #return void
*/
public function boot()
{
parent::boot();
}
}
The error:
When I run the command php artisan event:generate I get the following error:
PHP Fatal error: Call to a member function listens() on null in /app/vendor/laravel/framework/src/Illuminate/Foundation/Console/EventGenerateCommand.php on line 35
[Symfony\Component\Debug\Exception\FatalErrorException]
Call to a member function listens() on null
According to the doc, it should do this:
This command will generate any events or listeners that are listed in
your EventServiceProvider. Events and listeners that already exist
will be left untouched
I don't understant what I've missed since I didn't find any similar error by searching the web
This is the line that is returning null:
$providers = $this->laravel->getProviders(EventServiceProvider::class);
therefore, there are some problems with your EventServiceProvider... please, try using this:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* #var array
*/
protected $listen = [
'App\Events\FormBeforeCreate' => [
'App\Listeners\WebhookBeforeCreate',
],
'App\Events\FormAfterCreate' => [
'App\Listeners\NotifyAfterCreate',
'App\Listeners\WebhookAfterCreate',
],
'App\Events\FormBeforeUpdate' => [
'App\Listeners\WebhookBeforeUpdate',
],
'App\Events\FormAfterUpdate' => [
'App\Listeners\NotifyAfterUpdate',
'App\Listeners\WebhookAfterUpdate',
],
'App\Events\FormBeforeDelete' => [
'App\Listeners\WebhookBeforeDelete',
],
'App\Events\FormAfterDelete' => [
'App\Listeners\NotifyAfterDelete',
'App\Listeners\WebhookAfterDelete',
],
'App\Events\FormBeforeSave' => [
'App\Listeners\WebhookBeforeSave',
],
'App\Events\FormAfterSave' => [
'App\Listeners\NotifyAfterSave',
'App\Listeners\WebhookAfterSave',
],
];
/**
* Register any events for your application.
*
* #return void
*/
public function boot()
{
parent::boot();
//
}
}
My bad, it seems like I was really tired yesterday night, Our project runs on Docker, I was running the command outside of the docker instead of inside.
I have no idea why it showed this bug in particular but once I ran the command in the docker all files generated correctly.

Reflection Exception : Class does not exist for manually added class

I added a seeder (copied from elsewhere and pasted) to my application and included the call in the Database Seeder run() function. I get the exception above even though the class exists.
I suspected that maybe some files may have been cached so i cleared the application cache but i still get the same error.
DatabaseSeeder.php
<?php
use Illuminate\Database\Seeder;
class DatabaseSeeder extends Seeder
{
/**
* Seed the application's database.
*
* #return void
*/
public function run()
{
// $this->call(CustomersTableSeeder::class);
$this->call(RolesTableSeeder::class);
$this->call(ManagerStatesTableSeeder::class);
$this->call(ManagersTableSeeder::class);
$this->call(CountsTableSeeder::class);
$this->call(CategoriesTableSeeder::class);
}
}
Seeder file CategoriesTableSeeder.php
<?php
use Illuminate\Database\Seeder;
class CategoriesTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
\DB::table('categories')->insert([
[
'description' => 'Perfumes and Deo',
'slug' => 'perfumes-and-deo',
'parent' => 0,
'level' => 1,
'cna' => '2|',
'created_at' => \Carbon\Carbon::now(),
'updated_at' => \Carbon\Carbon::now(),
],
[
'description' => 'Perfumes',
'slug' => 'perfumes',
'parent' => 1,
'level' => 2,
'cna' => NULL,
'created_at' => \Carbon\Carbon::now(),
'updated_at' => \Carbon\Carbon::now(),
]
]);
}
}
Error:
ReflectionException : Class CategoriesTableSeeder does not exist
at C:\wamp\www\ma-sales-tracker\vendor\laravel\framework\src\Illuminate\Container\Container.php:788
Exception trace:
1 ReflectionClass::__construct("CategoriesTableSeeder")
C:\wamp\www\ma-sales-tracker\vendor\laravel\framework\src\Illuminate\Container\Container.php:788
2 Illuminate\Container\Container::build("CategoriesTableSeeder")
C:\wamp\www\ma-sales-tracker\vendor\laravel\framework\src\Illuminate\Container\Container.php:667
Any ideas on what might be causing this? Thanks in advance guys
I run Composer dump-autoload and voila! Worked as a charm. Also as suggested by Alex Mac, always generate Seeders with artisan commands.
Whenever you create any new file, always run following commands :-
composer dumpa // composer dump-autoload
php artisan optimize:clear // php artisan optimize:clear
because in bootstrap folder it keeps a track of each files and other configurations, etc.

Access to undeclared static property - Strange Issue

I got some strange situation, i working with laravel in php,
in my controllers i set "CompaniesController" and 2 more companies type controllers (Landlords & Clients).
got this error in the "ClientsController":
Access to undeclared static property: App\Http\Controllers\CRM\Pages\Companies\CompaniesController::$updates_roles
The clients & landlords controller reading the $updates_roles from CompaniesController, here is the code in the CompaniesController:
class CompaniesController extends Controller
{
/**
* Columns filters hide
*/
public static $columns_filters_hide = [
....
];
/**
* Allow Sorting Columns
*/
public static $columns_sorting = [
....
];
/**
* Query results values convert
*
* #var array
*/
public static $query_results_value = [
....
];
/**
* Updates Roles
*
* #var array
*/
public static $updates_roles = [
'Companies' =>
[
'primary' => 'id',
'fields' =>
[
'name' => [
'required' => true
],
'heb_name' => [
'required' => true
],
'website' => [],
'linkdin' => [],
'facebook' => [],
'phone' => [],
'notes' => [],
'kind' => [
'default' => 'ecosystem'
],
'rank' => ....
The problem is that all worked fine till now, and this error it's very strange becuase if i remove the file and his content, the page is still works, like it's in cache of something, the file now is uneditable, the var is not exists and i realy stuck here.
Thanks for help!
Problem solved!
CompaniesController already was exists in other namespace and the composer was built dump-autoload on the old path instead.
i removed the file from the old location and run composer dump-autoload and the problem solved.

Retrieve tstamp in extbase

I see that there's a 'last changed'-property in my table created with the extension builder called 'tstamp' but I can't figure out how to display it in the front-end.
In the front-end I'm using fluid like this, but it stays empty:
<f:format.date format="d.m.Y - H:i">{appointment.tstamp}</f:format.date>
I can see the property in the TCA also:
'ctrl' => array(
'title' => 'LLL:EXT:extTest/Resources/Private/Language/locallang_db.xlf:tx_extTest_domain_model_appointment',
'label' => 'start_date',
'tstamp' => 'tstamp',
I tried adding this in my php class file but it didn't change anything
/**
* #var DateTime
*/
protected $tstamp;
/**
* Get Tstamp
*
* #return DateTime
*/
public function getTstamp() {
return $this->tstamp;
}
I think the problem is that I don't understand the connection from the TCA to the PHP Class, can someone help?
The issue is that you also need a TCA configuration for every field as extbase gets there required information (especially for relations). Therefore add something like this into the TCA of your table:
'tstamp' => [
'label' => 'tstamp',
'config' => [
'type' => 'passthrough',
]
],
You don't need to add the field to a actual type.
The annotation in the model should be
/**
* #var \DateTime
*/
protected $tstamp;
So don't forget the \before the DateTime.
Clear caches and you are fine

Categories