test: add comprehensive test suite and model factories
- Add HasFactory trait to all model classes for factory support - Create factory classes for all models (Classification, Company, ContentRecap, Department, IssueManagement, Journalist, Location, MediaMonitoring, MediaMonitoringTheme, PartnerMedia, SubClassification, SubLocation, Theme, User) - Add unit tests for all models with relationship and attribute validation - Add unit tests for all enums (Channel, ContentType, IsActive, IssueSentiment, MediaClassification, MediaType, SocialMedia) - Add feature tests for factory integration and basic application functionality - Add tests for Filament actions, columns, and media library utilities - Add tests for model policies (Classification, Theme) and traits (WithComment, WithValue) - Update phpunit.xml configuration for test environment - Add test documentation and working tests reference guide - Add ContentType enum casting to ContentRecap model - Add MediaMonitoringTheme relationships and factory support - Establish comprehensive testing infrastructure for improved code quality and reliability
This commit is contained in:
parent
7522056280
commit
97cdfd6e0b
@ -5,13 +5,14 @@
|
|||||||
use App\Enums\IsActive;
|
use App\Enums\IsActive;
|
||||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
class Classification extends Model
|
class Classification extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use HasFactory, SoftDeletes;
|
||||||
|
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
|
||||||
@ -12,7 +13,7 @@
|
|||||||
|
|
||||||
class Company extends Model implements HasMedia
|
class Company extends Model implements HasMedia
|
||||||
{
|
{
|
||||||
use InteractsWithMedia, SoftDeletes;
|
use HasFactory, InteractsWithMedia, SoftDeletes;
|
||||||
|
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Enums\ContentType;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
@ -10,10 +12,18 @@
|
|||||||
|
|
||||||
class ContentRecap extends Model implements HasMedia
|
class ContentRecap extends Model implements HasMedia
|
||||||
{
|
{
|
||||||
use InteractsWithMedia, SoftDeletes;
|
use HasFactory, InteractsWithMedia, SoftDeletes;
|
||||||
|
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'type' => ContentType::class,
|
||||||
|
'posting_date' => 'date',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function classification(): BelongsTo
|
public function classification(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Classification::class);
|
return $this->belongsTo(Classification::class);
|
||||||
|
|||||||
@ -3,12 +3,13 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\Enums\IsActive;
|
use App\Enums\IsActive;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
class Department extends Model
|
class Department extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use HasFactory, SoftDeletes;
|
||||||
|
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
class IssueManagement extends Model
|
class IssueManagement extends Model
|
||||||
{
|
{
|
||||||
use HasFactory, SoftDeletes;
|
use HasFactory, HasFactory, SoftDeletes;
|
||||||
|
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
@ -10,7 +11,7 @@
|
|||||||
|
|
||||||
class Journalist extends Model implements HasMedia
|
class Journalist extends Model implements HasMedia
|
||||||
{
|
{
|
||||||
use InteractsWithMedia, SoftDeletes;
|
use HasFactory, InteractsWithMedia, SoftDeletes;
|
||||||
|
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
|||||||
@ -3,13 +3,14 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\Enums\IsActive;
|
use App\Enums\IsActive;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
class Location extends Model
|
class Location extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use HasFactory, SoftDeletes;
|
||||||
|
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||||
@ -11,7 +12,7 @@
|
|||||||
|
|
||||||
class MediaMonitoring extends Model implements HasMedia
|
class MediaMonitoring extends Model implements HasMedia
|
||||||
{
|
{
|
||||||
use InteractsWithMedia, SoftDeletes;
|
use HasFactory, InteractsWithMedia, SoftDeletes;
|
||||||
|
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
|||||||
@ -2,11 +2,25 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
|
|
||||||
class MediaMonitoringTheme extends Model
|
class MediaMonitoringTheme extends Model
|
||||||
{
|
{
|
||||||
|
use HasFactory;
|
||||||
|
|
||||||
protected $table = 'media_monitoring_theme';
|
protected $table = 'media_monitoring_theme';
|
||||||
|
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
public function mediaMonitoring(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(MediaMonitoring::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function theme(): BelongsTo
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Theme::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Enums\MediaClassification;
|
||||||
|
use App\Enums\MediaType;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
@ -11,10 +14,18 @@
|
|||||||
|
|
||||||
class PartnerMedia extends Model implements HasMedia
|
class PartnerMedia extends Model implements HasMedia
|
||||||
{
|
{
|
||||||
use InteractsWithMedia, SoftDeletes;
|
use HasFactory, InteractsWithMedia, SoftDeletes;
|
||||||
|
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
protected function casts(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'type' => MediaType::class,
|
||||||
|
'classification' => MediaClassification::class,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
public function company(): BelongsTo
|
public function company(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Company::class);
|
return $this->belongsTo(Company::class);
|
||||||
|
|||||||
@ -5,13 +5,14 @@
|
|||||||
use App\Enums\IsActive;
|
use App\Enums\IsActive;
|
||||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
class SubClassification extends Model
|
class SubClassification extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use HasFactory, SoftDeletes;
|
||||||
|
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
|||||||
@ -3,13 +3,14 @@
|
|||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\Enums\IsActive;
|
use App\Enums\IsActive;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
class SubLocation extends Model
|
class SubLocation extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use HasFactory, SoftDeletes;
|
||||||
|
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
|||||||
@ -5,13 +5,14 @@
|
|||||||
use App\Enums\IsActive;
|
use App\Enums\IsActive;
|
||||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
|
|
||||||
class Theme extends Model
|
class Theme extends Model
|
||||||
{
|
{
|
||||||
use SoftDeletes;
|
use HasFactory, SoftDeletes;
|
||||||
|
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
use Filament\Panel;
|
use Filament\Panel;
|
||||||
use Illuminate\Database\Eloquent\Attributes\Scope;
|
use Illuminate\Database\Eloquent\Attributes\Scope;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
@ -15,15 +16,18 @@
|
|||||||
|
|
||||||
class User extends Authenticatable implements FilamentUser
|
class User extends Authenticatable implements FilamentUser
|
||||||
{
|
{
|
||||||
use HasRoles, Notifiable, SoftDeletes;
|
use HasFactory, HasRoles, Notifiable, SoftDeletes;
|
||||||
|
|
||||||
protected $guarded = ['id'];
|
protected $guarded = ['id'];
|
||||||
|
|
||||||
|
protected $hidden = ['password', 'remember_token'];
|
||||||
|
|
||||||
protected function casts(): array
|
protected function casts(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'password' => 'hashed',
|
'password' => 'hashed',
|
||||||
'is_active' => IsActive::class,
|
'is_active' => IsActive::class,
|
||||||
|
'email_verified_at' => 'timestamp',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
"laravel/sail": "^1.41",
|
"laravel/sail": "^1.41",
|
||||||
"mockery/mockery": "^1.6",
|
"mockery/mockery": "^1.6",
|
||||||
"nunomaduro/collision": "^8.6",
|
"nunomaduro/collision": "^8.6",
|
||||||
"phpunit/phpunit": "^11.5.3"
|
"pestphp/pest": "^3.8"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
|||||||
995
composer.lock
generated
995
composer.lock
generated
File diff suppressed because it is too large
Load Diff
50
database/factories/ClassificationFactory.php
Normal file
50
database/factories/ClassificationFactory.php
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Enums\IsActive;
|
||||||
|
use App\Models\Classification;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Classification>
|
||||||
|
*/
|
||||||
|
class ClassificationFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = Classification::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => $this->faker->words(2, true),
|
||||||
|
'description' => $this->faker->sentence(),
|
||||||
|
'is_active' => $this->faker->randomElement([IsActive::ACTIVE->value, IsActive::INACTIVE->value]),
|
||||||
|
'sort_order' => $this->faker->numberBetween(0, 100),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the classification is active.
|
||||||
|
*/
|
||||||
|
public function active(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'is_active' => IsActive::ACTIVE->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the classification is inactive.
|
||||||
|
*/
|
||||||
|
public function inactive(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'is_active' => IsActive::INACTIVE->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
74
database/factories/CompanyFactory.php
Normal file
74
database/factories/CompanyFactory.php
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Company;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Company>
|
||||||
|
*/
|
||||||
|
class CompanyFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = Company::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'user_id' => User::factory(),
|
||||||
|
'name' => $this->faker->company(),
|
||||||
|
'email' => $this->faker->unique()->companyEmail(),
|
||||||
|
'address' => $this->faker->address(),
|
||||||
|
'director_name' => $this->faker->name(),
|
||||||
|
'director_nik' => $this->faker->numerify('################'),
|
||||||
|
'deed_incorporation' => $this->faker->numerify('AHU-#######.AH.##.##'),
|
||||||
|
'trade_license' => $this->faker->numerify('###/###/SIUP/####'),
|
||||||
|
'tax_id_number' => $this->faker->numerify('##.###.###.#-###.###'),
|
||||||
|
'taxable_enterprise' => $this->faker->numerify('###.###.###.###'),
|
||||||
|
'annual_tax_return' => $this->faker->numerify('SPT-####-########'),
|
||||||
|
'domicile_certificate' => $this->faker->numerify('###/###/DOMISILI/####'),
|
||||||
|
'profile' => $this->faker->numerify('PROFILE-####-########'),
|
||||||
|
'validated_at' => $this->faker->optional(0.7)->dateTimeBetween('-1 year', 'now'),
|
||||||
|
'rejection_reason' => $this->faker->optional(0.1)->sentence(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the company is validated.
|
||||||
|
*/
|
||||||
|
public function validated(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'validated_at' => $this->faker->dateTimeBetween('-6 months', 'now'),
|
||||||
|
'rejection_reason' => null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the company is rejected.
|
||||||
|
*/
|
||||||
|
public function rejected(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'validated_at' => null,
|
||||||
|
'rejection_reason' => $this->faker->sentence(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the company is pending validation.
|
||||||
|
*/
|
||||||
|
public function pending(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'validated_at' => null,
|
||||||
|
'rejection_reason' => null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
121
database/factories/ContentRecapFactory.php
Normal file
121
database/factories/ContentRecapFactory.php
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Enums\ContentType;
|
||||||
|
use App\Models\Classification;
|
||||||
|
use App\Models\ContentRecap;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\ContentRecap>
|
||||||
|
*/
|
||||||
|
class ContentRecapFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = ContentRecap::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
$channels = [
|
||||||
|
'Website',
|
||||||
|
'Facebook',
|
||||||
|
'Instagram',
|
||||||
|
'Twitter',
|
||||||
|
'YouTube',
|
||||||
|
'TikTok',
|
||||||
|
'WhatsApp',
|
||||||
|
'Telegram',
|
||||||
|
'LinkedIn',
|
||||||
|
];
|
||||||
|
|
||||||
|
$socialMediaPlatforms = [
|
||||||
|
'Facebook',
|
||||||
|
'Instagram',
|
||||||
|
'Twitter',
|
||||||
|
'YouTube',
|
||||||
|
'TikTok',
|
||||||
|
'LinkedIn',
|
||||||
|
'WhatsApp',
|
||||||
|
'Telegram',
|
||||||
|
'Pinterest',
|
||||||
|
];
|
||||||
|
|
||||||
|
return [
|
||||||
|
'classification_id' => Classification::factory(),
|
||||||
|
'title' => $this->faker->sentence(4),
|
||||||
|
'link' => $this->faker->optional(0.8)->url(),
|
||||||
|
'posting_date' => $this->faker->dateTimeBetween('-6 months', 'now')->format('Y-m-d'),
|
||||||
|
'type' => $this->faker->randomElement(ContentType::cases())->value,
|
||||||
|
'channel' => $this->faker->randomElement($channels),
|
||||||
|
'social_media' => $this->faker->randomElement($socialMediaPlatforms),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the content recap is photo type.
|
||||||
|
*/
|
||||||
|
public function photo(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'type' => ContentType::FOTO->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the content recap is video type.
|
||||||
|
*/
|
||||||
|
public function video(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'type' => ContentType::VIDEO->value,
|
||||||
|
'channel' => $this->faker->randomElement(['YouTube', 'Instagram', 'TikTok']),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the content recap is text type.
|
||||||
|
*/
|
||||||
|
public function text(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'type' => ContentType::TEXT->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the content recap is graphic type.
|
||||||
|
*/
|
||||||
|
public function graphic(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'type' => ContentType::GRAPHIC->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the content recap is for Instagram.
|
||||||
|
*/
|
||||||
|
public function instagram(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'channel' => 'Instagram',
|
||||||
|
'social_media' => 'Instagram',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the content recap is for Facebook.
|
||||||
|
*/
|
||||||
|
public function facebook(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'channel' => 'Facebook',
|
||||||
|
'social_media' => 'Facebook',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
61
database/factories/DepartmentFactory.php
Normal file
61
database/factories/DepartmentFactory.php
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Enums\IsActive;
|
||||||
|
use App\Models\Department;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Department>
|
||||||
|
*/
|
||||||
|
class DepartmentFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = Department::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
$name = $this->faker->randomElement([
|
||||||
|
'Dinas Komunikasi dan Informatika',
|
||||||
|
'Dinas Pendidikan',
|
||||||
|
'Dinas Kesehatan',
|
||||||
|
'Dinas Pekerjaan Umum',
|
||||||
|
'Dinas Sosial',
|
||||||
|
'Dinas Pariwisata',
|
||||||
|
'Dinas Perhubungan',
|
||||||
|
'Dinas Lingkungan Hidup',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'name' => $name,
|
||||||
|
'alias' => strtoupper(substr(str_replace(['Dinas ', ' dan ', ' '], ['', '', ''], $name), 0, 10)),
|
||||||
|
'is_active' => $this->faker->randomElement([IsActive::ACTIVE->value, IsActive::INACTIVE->value]),
|
||||||
|
'sort_order' => $this->faker->numberBetween(0, 100),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the department is active.
|
||||||
|
*/
|
||||||
|
public function active(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'is_active' => IsActive::ACTIVE->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the department is inactive.
|
||||||
|
*/
|
||||||
|
public function inactive(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'is_active' => IsActive::INACTIVE->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
109
database/factories/IssueManagementFactory.php
Normal file
109
database/factories/IssueManagementFactory.php
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Enums\IssueSentiment;
|
||||||
|
use App\Models\Classification;
|
||||||
|
use App\Models\IssueManagement;
|
||||||
|
use App\Models\Location;
|
||||||
|
use App\Models\MediaMonitoring;
|
||||||
|
use App\Models\SubClassification;
|
||||||
|
use App\Models\SubLocation;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\IssueManagement>
|
||||||
|
*/
|
||||||
|
class IssueManagementFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = IssueManagement::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'location_id' => Location::factory(),
|
||||||
|
'sub_location_id' => SubLocation::factory(),
|
||||||
|
'classification_id' => Classification::factory(),
|
||||||
|
'sub_classification_id' => SubClassification::factory(),
|
||||||
|
'media_monitoring_id' => MediaMonitoring::factory(),
|
||||||
|
'issue' => $this->faker->randomElement(IssueSentiment::cases())->value,
|
||||||
|
'response' => $this->faker->randomElement(IssueSentiment::cases())->value,
|
||||||
|
'description' => $this->faker->paragraphs(2, true),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the issue is positive.
|
||||||
|
*/
|
||||||
|
public function positive(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'issue' => IssueSentiment::POSITIVE->value,
|
||||||
|
'response' => IssueSentiment::POSITIVE->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the issue is negative.
|
||||||
|
*/
|
||||||
|
public function negative(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'issue' => IssueSentiment::NEGATIVE->value,
|
||||||
|
'response' => $this->faker->randomElement([
|
||||||
|
IssueSentiment::POSITIVE->value,
|
||||||
|
IssueSentiment::NEUTRAL->value,
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the issue is neutral.
|
||||||
|
*/
|
||||||
|
public function neutral(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'issue' => IssueSentiment::NEUTRAL->value,
|
||||||
|
'response' => IssueSentiment::NEUTRAL->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the issue is crisis.
|
||||||
|
*/
|
||||||
|
public function crisis(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'issue' => IssueSentiment::CRISIS->value,
|
||||||
|
'response' => $this->faker->randomElement([
|
||||||
|
IssueSentiment::POSITIVE->value,
|
||||||
|
IssueSentiment::NEUTRAL->value,
|
||||||
|
]),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the issue has no sub location.
|
||||||
|
*/
|
||||||
|
public function withoutSubLocation(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'sub_location_id' => null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the issue has no sub classification.
|
||||||
|
*/
|
||||||
|
public function withoutSubClassification(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'sub_classification_id' => null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
54
database/factories/JournalistFactory.php
Normal file
54
database/factories/JournalistFactory.php
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Journalist;
|
||||||
|
use App\Models\PartnerMedia;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Journalist>
|
||||||
|
*/
|
||||||
|
class JournalistFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = Journalist::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'partner_media_id' => PartnerMedia::factory(),
|
||||||
|
'name' => $this->faker->name(),
|
||||||
|
'email' => $this->faker->unique()->safeEmail(),
|
||||||
|
'phone_number' => $this->faker->phoneNumber(),
|
||||||
|
'press_card' => $this->faker->optional(0.8)->numerify('PWI-####-########'),
|
||||||
|
'ukw_certificate' => $this->faker->optional(0.6)->numerify('UKW-####-########'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the journalist has press credentials.
|
||||||
|
*/
|
||||||
|
public function withCredentials(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'press_card' => $this->faker->numerify('PWI-####-########'),
|
||||||
|
'ukw_certificate' => $this->faker->numerify('UKW-####-########'),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the journalist has no credentials.
|
||||||
|
*/
|
||||||
|
public function withoutCredentials(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'press_card' => null,
|
||||||
|
'ukw_certificate' => null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
50
database/factories/LocationFactory.php
Normal file
50
database/factories/LocationFactory.php
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Enums\IsActive;
|
||||||
|
use App\Models\Location;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Location>
|
||||||
|
*/
|
||||||
|
class LocationFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = Location::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => $this->faker->city(),
|
||||||
|
'description' => $this->faker->sentence(),
|
||||||
|
'is_active' => $this->faker->randomElement([IsActive::ACTIVE->value, IsActive::INACTIVE->value]),
|
||||||
|
'sort_order' => $this->faker->numberBetween(0, 100),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the location is active.
|
||||||
|
*/
|
||||||
|
public function active(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'is_active' => IsActive::ACTIVE->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the location is inactive.
|
||||||
|
*/
|
||||||
|
public function inactive(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'is_active' => IsActive::INACTIVE->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
106
database/factories/MediaMonitoringFactory.php
Normal file
106
database/factories/MediaMonitoringFactory.php
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\MediaMonitoring;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\MediaMonitoring>
|
||||||
|
*/
|
||||||
|
class MediaMonitoringFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = MediaMonitoring::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
$mediaNames = [
|
||||||
|
'Kompas.com',
|
||||||
|
'Detik.com',
|
||||||
|
'Tribun News',
|
||||||
|
'Liputan6',
|
||||||
|
'CNN Indonesia',
|
||||||
|
'ANTARA News',
|
||||||
|
'Tempo.co',
|
||||||
|
'Okezone',
|
||||||
|
'Suara.com',
|
||||||
|
'Bisnis.com',
|
||||||
|
];
|
||||||
|
|
||||||
|
$channels = [
|
||||||
|
'Website',
|
||||||
|
'Facebook',
|
||||||
|
'Instagram',
|
||||||
|
'Twitter',
|
||||||
|
'YouTube',
|
||||||
|
'TikTok',
|
||||||
|
'WhatsApp',
|
||||||
|
'Telegram',
|
||||||
|
'LinkedIn',
|
||||||
|
];
|
||||||
|
|
||||||
|
return [
|
||||||
|
'code' => $this->faker->unique()->regexify('[A-Z]{2}[0-9]{8}'),
|
||||||
|
'media_name' => $this->faker->randomElement($mediaNames),
|
||||||
|
'title' => $this->faker->sentence(6),
|
||||||
|
'channel' => $this->faker->randomElement($channels),
|
||||||
|
'writter' => $this->faker->name(),
|
||||||
|
'link' => $this->faker->optional(0.8)->url(),
|
||||||
|
'news_page' => $this->faker->optional(0.3)->numberBetween(1, 20),
|
||||||
|
'quote' => $this->faker->optional(0.4)->paragraph(),
|
||||||
|
'content' => $this->faker->paragraphs(3, true),
|
||||||
|
'influencer' => $this->faker->optional(0.2)->name(),
|
||||||
|
'keyword' => implode(', ', $this->faker->words(3)),
|
||||||
|
'release_date' => $this->faker->dateTimeBetween('-1 year', 'now')->format('Y-m-d'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the media monitoring is for online media.
|
||||||
|
*/
|
||||||
|
public function online(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'channel' => $this->faker->randomElement(['Website', 'Facebook', 'Instagram', 'Twitter']),
|
||||||
|
'link' => $this->faker->url(),
|
||||||
|
'news_page' => null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the media monitoring is for print media.
|
||||||
|
*/
|
||||||
|
public function print(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'channel' => 'Print',
|
||||||
|
'link' => null,
|
||||||
|
'news_page' => $this->faker->numberBetween(1, 20),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the media monitoring has influencer mention.
|
||||||
|
*/
|
||||||
|
public function withInfluencer(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'influencer' => $this->faker->name(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the media monitoring has quote.
|
||||||
|
*/
|
||||||
|
public function withQuote(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'quote' => $this->faker->paragraph(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
29
database/factories/MediaMonitoringThemeFactory.php
Normal file
29
database/factories/MediaMonitoringThemeFactory.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\MediaMonitoring;
|
||||||
|
use App\Models\MediaMonitoringTheme;
|
||||||
|
use App\Models\Theme;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\MediaMonitoringTheme>
|
||||||
|
*/
|
||||||
|
class MediaMonitoringThemeFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = MediaMonitoringTheme::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'media_monitoring_id' => MediaMonitoring::factory(),
|
||||||
|
'theme_id' => Theme::factory(),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
120
database/factories/PartnerMediaFactory.php
Normal file
120
database/factories/PartnerMediaFactory.php
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Enums\MediaClassification;
|
||||||
|
use App\Enums\MediaType;
|
||||||
|
use App\Models\Company;
|
||||||
|
use App\Models\PartnerMedia;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\PartnerMedia>
|
||||||
|
*/
|
||||||
|
class PartnerMediaFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = PartnerMedia::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
$mediaNames = [
|
||||||
|
'Kompas.com',
|
||||||
|
'Detik.com',
|
||||||
|
'Tribun News',
|
||||||
|
'Liputan6',
|
||||||
|
'CNN Indonesia',
|
||||||
|
'ANTARA News',
|
||||||
|
'Tempo.co',
|
||||||
|
'Okezone',
|
||||||
|
'Suara.com',
|
||||||
|
'Bisnis.com',
|
||||||
|
'Media Indonesia',
|
||||||
|
'Republika',
|
||||||
|
'Koran Sindo',
|
||||||
|
'Pikiran Rakyat',
|
||||||
|
];
|
||||||
|
|
||||||
|
return [
|
||||||
|
'company_id' => Company::factory(),
|
||||||
|
'name' => $this->faker->randomElement($mediaNames),
|
||||||
|
'address' => $this->faker->address(),
|
||||||
|
'link' => $this->faker->optional(0.8)->url(),
|
||||||
|
'type' => $this->faker->randomElement(MediaType::cases())->value,
|
||||||
|
'classification' => $this->faker->randomElement(MediaClassification::cases())->value,
|
||||||
|
'journalism_organization' => $this->faker->optional(0.6)->randomElement([
|
||||||
|
'Persatuan Wartawan Indonesia (PWI)',
|
||||||
|
'Aliansi Jurnalis Independen (AJI)',
|
||||||
|
'Ikatan Jurnalis Televisi Indonesia (IJTI)',
|
||||||
|
'Persatuan Jurnalis Online Indonesia (PJOI)',
|
||||||
|
]),
|
||||||
|
'press_council_certificate' => $this->faker->optional(0.7)->numerify('DEP-###/####/KP'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the partner media is online type.
|
||||||
|
*/
|
||||||
|
public function online(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'type' => MediaType::ONLINE->value,
|
||||||
|
'link' => $this->faker->url(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the partner media is print type.
|
||||||
|
*/
|
||||||
|
public function print(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'type' => MediaType::PRINT->value,
|
||||||
|
'link' => null,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the partner media is television type.
|
||||||
|
*/
|
||||||
|
public function television(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'type' => MediaType::TELEVISION->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the partner media is radio type.
|
||||||
|
*/
|
||||||
|
public function radio(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'type' => MediaType::RADIO->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the partner media is national classification.
|
||||||
|
*/
|
||||||
|
public function national(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'classification' => MediaClassification::NATIONAL->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the partner media is local classification.
|
||||||
|
*/
|
||||||
|
public function local(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'classification' => MediaClassification::LOCAL->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
52
database/factories/SubClassificationFactory.php
Normal file
52
database/factories/SubClassificationFactory.php
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Enums\IsActive;
|
||||||
|
use App\Models\Classification;
|
||||||
|
use App\Models\SubClassification;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\SubClassification>
|
||||||
|
*/
|
||||||
|
class SubClassificationFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = SubClassification::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'classification_id' => Classification::factory(),
|
||||||
|
'name' => $this->faker->words(2, true),
|
||||||
|
'description' => $this->faker->sentence(),
|
||||||
|
'is_active' => $this->faker->randomElement([IsActive::ACTIVE->value, IsActive::INACTIVE->value]),
|
||||||
|
'sort_order' => $this->faker->numberBetween(0, 100),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the sub classification is active.
|
||||||
|
*/
|
||||||
|
public function active(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'is_active' => IsActive::ACTIVE->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the sub classification is inactive.
|
||||||
|
*/
|
||||||
|
public function inactive(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'is_active' => IsActive::INACTIVE->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
52
database/factories/SubLocationFactory.php
Normal file
52
database/factories/SubLocationFactory.php
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Enums\IsActive;
|
||||||
|
use App\Models\Location;
|
||||||
|
use App\Models\SubLocation;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\SubLocation>
|
||||||
|
*/
|
||||||
|
class SubLocationFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = SubLocation::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'location_id' => Location::factory(),
|
||||||
|
'name' => $this->faker->streetName(),
|
||||||
|
'description' => $this->faker->sentence(),
|
||||||
|
'is_active' => $this->faker->randomElement([IsActive::ACTIVE->value, IsActive::INACTIVE->value]),
|
||||||
|
'sort_order' => $this->faker->numberBetween(0, 100),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the sub location is active.
|
||||||
|
*/
|
||||||
|
public function active(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'is_active' => IsActive::ACTIVE->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the sub location is inactive.
|
||||||
|
*/
|
||||||
|
public function inactive(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'is_active' => IsActive::INACTIVE->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
49
database/factories/ThemeFactory.php
Normal file
49
database/factories/ThemeFactory.php
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Enums\IsActive;
|
||||||
|
use App\Models\Theme;
|
||||||
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Theme>
|
||||||
|
*/
|
||||||
|
class ThemeFactory extends Factory
|
||||||
|
{
|
||||||
|
protected $model = Theme::class;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Define the model's default state.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function definition(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'name' => $this->faker->words(2, true),
|
||||||
|
'is_active' => $this->faker->randomElement([IsActive::ACTIVE->value, IsActive::INACTIVE->value]),
|
||||||
|
'sort_order' => $this->faker->numberBetween(0, 100),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the theme is active.
|
||||||
|
*/
|
||||||
|
public function active(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'is_active' => IsActive::ACTIVE->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicate that the theme is inactive.
|
||||||
|
*/
|
||||||
|
public function inactive(): static
|
||||||
|
{
|
||||||
|
return $this->state(fn (array $attributes) => [
|
||||||
|
'is_active' => IsActive::INACTIVE->value,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -26,6 +26,7 @@ public function definition(): array
|
|||||||
return [
|
return [
|
||||||
'name' => fake()->name(),
|
'name' => fake()->name(),
|
||||||
'email' => fake()->unique()->safeEmail(),
|
'email' => fake()->unique()->safeEmail(),
|
||||||
|
'username' => $this->faker->unique()->userName(),
|
||||||
'email_verified_at' => now(),
|
'email_verified_at' => now(),
|
||||||
'password' => static::$password ??= Hash::make('password'),
|
'password' => static::$password ??= Hash::make('password'),
|
||||||
'remember_token' => Str::random(10),
|
'remember_token' => Str::random(10),
|
||||||
|
|||||||
@ -21,15 +21,14 @@
|
|||||||
<env name="APP_ENV" value="testing"/>
|
<env name="APP_ENV" value="testing"/>
|
||||||
<env name="APP_MAINTENANCE_DRIVER" value="file"/>
|
<env name="APP_MAINTENANCE_DRIVER" value="file"/>
|
||||||
<env name="BCRYPT_ROUNDS" value="4"/>
|
<env name="BCRYPT_ROUNDS" value="4"/>
|
||||||
<env name="BROADCAST_CONNECTION" value="null"/>
|
|
||||||
<env name="CACHE_STORE" value="array"/>
|
<env name="CACHE_STORE" value="array"/>
|
||||||
<env name="DB_CONNECTION" value="sqlite"/>
|
<env name="DB_CONNECTION" value="sqlite"/>
|
||||||
<env name="DB_DATABASE" value=":memory:"/>
|
<env name="DB_DATABASE" value=":memory:"/>
|
||||||
<env name="MAIL_MAILER" value="array"/>
|
<env name="MAIL_MAILER" value="array"/>
|
||||||
|
<env name="PULSE_ENABLED" value="false"/>
|
||||||
<env name="QUEUE_CONNECTION" value="sync"/>
|
<env name="QUEUE_CONNECTION" value="sync"/>
|
||||||
<env name="SESSION_DRIVER" value="array"/>
|
<env name="SESSION_DRIVER" value="array"/>
|
||||||
<env name="PULSE_ENABLED" value="false"/>
|
|
||||||
<env name="TELESCOPE_ENABLED" value="false"/>
|
<env name="TELESCOPE_ENABLED" value="false"/>
|
||||||
<env name="NIGHTWATCH_ENABLED" value="false"/>
|
<env name="VITE_TEST_BUILD" value="true"/>
|
||||||
</php>
|
</php>
|
||||||
</phpunit>
|
</phpunit>
|
||||||
|
|||||||
21
tests/CreatesApplication.php
Normal file
21
tests/CreatesApplication.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests;
|
||||||
|
|
||||||
|
use Illuminate\Contracts\Console\Kernel;
|
||||||
|
use Illuminate\Foundation\Application;
|
||||||
|
|
||||||
|
trait CreatesApplication
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Creates the application.
|
||||||
|
*/
|
||||||
|
public function createApplication(): Application
|
||||||
|
{
|
||||||
|
$app = require __DIR__.'/../bootstrap/app.php';
|
||||||
|
|
||||||
|
$app->make(Kernel::class)->bootstrap();
|
||||||
|
|
||||||
|
return $app;
|
||||||
|
}
|
||||||
|
}
|
||||||
97
tests/Feature/BasicFactoryTest.php
Normal file
97
tests/Feature/BasicFactoryTest.php
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Classification;
|
||||||
|
use App\Models\Company;
|
||||||
|
use App\Models\ContentRecap;
|
||||||
|
use App\Models\Department;
|
||||||
|
use App\Models\IssueManagement;
|
||||||
|
use App\Models\Journalist;
|
||||||
|
use App\Models\Location;
|
||||||
|
use App\Models\MediaMonitoring;
|
||||||
|
use App\Models\PartnerMedia;
|
||||||
|
use App\Models\Theme;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
describe('Basic Factory Tests', function () {
|
||||||
|
it('can create theme using factory', function () {
|
||||||
|
$theme = Theme::factory()->create();
|
||||||
|
|
||||||
|
expect($theme)->toBeInstanceOf(Theme::class)
|
||||||
|
->and($theme->exists)->toBeTrue()
|
||||||
|
->and($theme->name)->toBeString();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create classification using factory', function () {
|
||||||
|
$classification = Classification::factory()->create();
|
||||||
|
|
||||||
|
expect($classification)->toBeInstanceOf(Classification::class)
|
||||||
|
->and($classification->exists)->toBeTrue()
|
||||||
|
->and($classification->name)->toBeString();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create location using factory', function () {
|
||||||
|
$location = Location::factory()->create();
|
||||||
|
|
||||||
|
expect($location)->toBeInstanceOf(Location::class)
|
||||||
|
->and($location->exists)->toBeTrue()
|
||||||
|
->and($location->name)->toBeString();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create department using factory', function () {
|
||||||
|
$department = Department::factory()->create();
|
||||||
|
|
||||||
|
expect($department)->toBeInstanceOf(Department::class)
|
||||||
|
->and($department->exists)->toBeTrue()
|
||||||
|
->and($department->name)->toBeString()
|
||||||
|
->and($department->alias)->toBeString();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create company using factory', function () {
|
||||||
|
$company = Company::factory()->create();
|
||||||
|
expect($company)->toBeInstanceOf(Company::class)
|
||||||
|
->and($company->exists)->toBeTrue()
|
||||||
|
->and($company->name)->toBeString();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create partner media using factory', function () {
|
||||||
|
$partnerMedia = PartnerMedia::factory()->create();
|
||||||
|
|
||||||
|
expect($partnerMedia)->toBeInstanceOf(PartnerMedia::class)
|
||||||
|
->and($partnerMedia->exists)->toBeTrue()
|
||||||
|
->and($partnerMedia->name)->toBeString();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create journalist using factory', function () {
|
||||||
|
$journalist = Journalist::factory()->create();
|
||||||
|
|
||||||
|
expect($journalist)->toBeInstanceOf(Journalist::class)
|
||||||
|
->and($journalist->exists)->toBeTrue()
|
||||||
|
->and($journalist->name)->toBeString();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create media monitoring using factory', function () {
|
||||||
|
$mediaMonitoring = MediaMonitoring::factory()->create();
|
||||||
|
|
||||||
|
expect($mediaMonitoring)->toBeInstanceOf(MediaMonitoring::class)
|
||||||
|
->and($mediaMonitoring->exists)->toBeTrue()
|
||||||
|
->and($mediaMonitoring->title)->toBeString();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create content recap using factory', function () {
|
||||||
|
$contentRecap = ContentRecap::factory()->create();
|
||||||
|
|
||||||
|
expect($contentRecap)->toBeInstanceOf(ContentRecap::class)
|
||||||
|
->and($contentRecap->exists)->toBeTrue()
|
||||||
|
->and($contentRecap->title)->toBeString();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create issue management using factory', function () {
|
||||||
|
$issueManagement = IssueManagement::factory()->create();
|
||||||
|
|
||||||
|
expect($issueManagement)->toBeInstanceOf(IssueManagement::class)
|
||||||
|
->and($issueManagement->exists)->toBeTrue()
|
||||||
|
->and($issueManagement->description)->toBeString();
|
||||||
|
});
|
||||||
|
});
|
||||||
98
tests/Feature/IntegrationTest.php
Normal file
98
tests/Feature/IntegrationTest.php
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\IsActive;
|
||||||
|
use App\Enums\IssueSentiment;
|
||||||
|
use App\Enums\MediaType;
|
||||||
|
use App\Models\Classification;
|
||||||
|
use App\Models\Company;
|
||||||
|
use App\Models\IssueManagement;
|
||||||
|
use App\Models\Journalist;
|
||||||
|
use App\Models\MediaMonitoring;
|
||||||
|
use App\Models\PartnerMedia;
|
||||||
|
use App\Models\Theme;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
describe('Integration Tests', function () {
|
||||||
|
it('can create complete media monitoring workflow', function () {
|
||||||
|
// Create theme
|
||||||
|
$theme = Theme::factory()->create(['name' => 'Politik']);
|
||||||
|
|
||||||
|
// Create media monitoring
|
||||||
|
$mediaMonitoring = MediaMonitoring::factory()->create([
|
||||||
|
'title' => 'Berita Politik Terkini',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Attach theme to media monitoring
|
||||||
|
$mediaMonitoring->themes()->attach($theme->id);
|
||||||
|
|
||||||
|
// Verify relationships
|
||||||
|
expect($mediaMonitoring->themes)->toHaveCount(1)
|
||||||
|
->and($mediaMonitoring->themes->first()->name)->toBe('Politik');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create complete journalist workflow', function () {
|
||||||
|
// Create company
|
||||||
|
$company = Company::factory()->create(['name' => 'Media Indonesia']);
|
||||||
|
|
||||||
|
// Create partner media
|
||||||
|
$partnerMedia = PartnerMedia::factory()->create([
|
||||||
|
'company_id' => $company->id,
|
||||||
|
'name' => 'Kompas.com',
|
||||||
|
'type' => MediaType::ONLINE,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Create journalist
|
||||||
|
$journalist = Journalist::factory()->create([
|
||||||
|
'partner_media_id' => $partnerMedia->id,
|
||||||
|
'name' => 'John Doe',
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Verify relationships
|
||||||
|
expect($journalist->partnerMedia->company->name)->toBe('Media Indonesia')
|
||||||
|
->and($journalist->partnerMedia->type)->toBe(MediaType::ONLINE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create issue management with sentiment', function () {
|
||||||
|
// Create classification
|
||||||
|
$classification = Classification::factory()->create(['name' => 'Infrastruktur']);
|
||||||
|
|
||||||
|
// Create media monitoring
|
||||||
|
$mediaMonitoring = MediaMonitoring::factory()->create();
|
||||||
|
|
||||||
|
// Create issue management
|
||||||
|
$issue = IssueManagement::factory()->create([
|
||||||
|
'classification_id' => $classification->id,
|
||||||
|
'media_monitoring_id' => $mediaMonitoring->id,
|
||||||
|
'issue' => IssueSentiment::POSITIVE,
|
||||||
|
'response' => IssueSentiment::POSITIVE,
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Verify data
|
||||||
|
expect($issue->classification->name)->toBe('Infrastruktur')
|
||||||
|
->and($issue->issue)->toBe(IssueSentiment::POSITIVE)
|
||||||
|
->and($issue->response)->toBe(IssueSentiment::POSITIVE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can filter active records', function () {
|
||||||
|
// Create active and inactive themes
|
||||||
|
Theme::factory()->create(['is_active' => IsActive::ACTIVE]);
|
||||||
|
Theme::factory()->create(['is_active' => IsActive::INACTIVE]);
|
||||||
|
|
||||||
|
$activeThemes = Theme::active()->get();
|
||||||
|
|
||||||
|
expect($activeThemes)->toHaveCount(1)
|
||||||
|
->and($activeThemes->first()->is_active)->toBe(IsActive::ACTIVE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('verifies enum casting works correctly', function () {
|
||||||
|
$partnerMedia = PartnerMedia::factory()->create([
|
||||||
|
'type' => MediaType::TELEVISION,
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect($partnerMedia->type)->toBeInstanceOf(MediaType::class)
|
||||||
|
->and($partnerMedia->type)->toBe(MediaType::TELEVISION)
|
||||||
|
->and($partnerMedia->type->getLabel())->toBe('Televisi');
|
||||||
|
});
|
||||||
|
});
|
||||||
73
tests/Feature/ModelFactoryTest.php
Normal file
73
tests/Feature/ModelFactoryTest.php
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Classification;
|
||||||
|
use App\Models\Company;
|
||||||
|
use App\Models\ContentRecap;
|
||||||
|
use App\Models\Department;
|
||||||
|
use App\Models\IssueManagement;
|
||||||
|
use App\Models\Journalist;
|
||||||
|
use App\Models\Location;
|
||||||
|
use App\Models\MediaMonitoring;
|
||||||
|
use App\Models\PartnerMedia;
|
||||||
|
use App\Models\Theme;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
describe('Model Factory Tests', function () {
|
||||||
|
it('can create user', function () {
|
||||||
|
$user = User::factory()->create();
|
||||||
|
expect($user->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create theme', function () {
|
||||||
|
$theme = Theme::factory()->create();
|
||||||
|
expect($theme->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create classification', function () {
|
||||||
|
$classification = Classification::factory()->create();
|
||||||
|
expect($classification->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create location', function () {
|
||||||
|
$location = Location::factory()->create();
|
||||||
|
expect($location->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create department', function () {
|
||||||
|
$department = Department::factory()->create();
|
||||||
|
expect($department->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create company', function () {
|
||||||
|
$company = Company::factory()->create();
|
||||||
|
expect($company->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create partner media', function () {
|
||||||
|
$partnerMedia = PartnerMedia::factory()->create();
|
||||||
|
expect($partnerMedia->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create journalist', function () {
|
||||||
|
$journalist = Journalist::factory()->create();
|
||||||
|
expect($journalist->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create media monitoring', function () {
|
||||||
|
$mediaMonitoring = MediaMonitoring::factory()->create();
|
||||||
|
expect($mediaMonitoring->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create content recap', function () {
|
||||||
|
$contentRecap = ContentRecap::factory()->create();
|
||||||
|
expect($contentRecap->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can create issue management', function () {
|
||||||
|
$issueManagement = IssueManagement::factory()->create();
|
||||||
|
expect($issueManagement->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
});
|
||||||
47
tests/Pest.php
Normal file
47
tests/Pest.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Test Case
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| The closure you provide to your test functions is always bound to a specific PHPUnit test
|
||||||
|
| case class. By default, that class is "PHPUnit\Framework\TestCase". Of course, you may
|
||||||
|
| need to change it using the "uses()" function to bind a different classes or traits.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
uses(TestCase::class)->in('Feature', 'Unit');
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Expectations
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| When you're writing tests, you often need to check that values meet certain conditions. The
|
||||||
|
| "expect()" function gives you access to a set of "expectations" methods that you can use
|
||||||
|
| to assert different things. Of course, you may extend the Expectation API at any time.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
expect()->extend('toBeOne', function () {
|
||||||
|
return $this->toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
/*
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
| Functions
|
||||||
|
|--------------------------------------------------------------------------
|
||||||
|
|
|
||||||
|
| While Pest is very powerful out-of-the-box, you may have some testing code specific to your
|
||||||
|
| project that you don't want to repeat in every file. Here you can also expose helpers as
|
||||||
|
| global functions to help you to reduce the amount of code you need to type in your tests.
|
||||||
|
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
function something()
|
||||||
|
{
|
||||||
|
// ..
|
||||||
|
}
|
||||||
191
tests/README.md
Normal file
191
tests/README.md
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
# SIMEDKOM Testing Suite
|
||||||
|
|
||||||
|
Comprehensive Pest testing suite for the SIMEDKOM media monitoring and management system.
|
||||||
|
|
||||||
|
## Test Structure
|
||||||
|
|
||||||
|
### Unit Tests (`tests/Unit/`)
|
||||||
|
|
||||||
|
#### Enums (`tests/Unit/Enums/`)
|
||||||
|
- `MediaTypeTest.php` - Tests for media type enumeration
|
||||||
|
- `ContentTypeTest.php` - Tests for content type enumeration
|
||||||
|
- `IssueSentimentTest.php` - Tests for issue sentiment enumeration
|
||||||
|
- `IsActiveTest.php` - Tests for active status enumeration
|
||||||
|
- `ChannelTest.php` - Tests for channel enumeration
|
||||||
|
- `MediaClassificationTest.php` - Tests for media classification enumeration
|
||||||
|
- `SocialMediaTest.php` - Tests for social media platform enumeration
|
||||||
|
|
||||||
|
#### Models (`tests/Unit/Models/`)
|
||||||
|
- `UserTest.php` - User model tests
|
||||||
|
- `ThemeTest.php` - Theme model tests and relationships
|
||||||
|
- `ClassificationTest.php` - Classification model tests and relationships
|
||||||
|
- `SubClassificationTest.php` - Sub-classification model tests
|
||||||
|
- `LocationTest.php` - Location model tests and relationships
|
||||||
|
- `SubLocationTest.php` - Sub-location model tests
|
||||||
|
- `DepartmentTest.php` - Department model tests
|
||||||
|
- `MediaMonitoringTest.php` - Media monitoring model tests and relationships
|
||||||
|
- `MediaMonitoringThemeTest.php` - Pivot model tests
|
||||||
|
- `IssueManagementTest.php` - Issue management model tests
|
||||||
|
- `ContentRecapTest.php` - Content recap model tests
|
||||||
|
- `JournalistTest.php` - Journalist model tests and relationships
|
||||||
|
- `CompanyTest.php` - Company model tests and relationships
|
||||||
|
- `PartnerMediaTest.php` - Partner media model tests
|
||||||
|
|
||||||
|
#### Policies (`tests/Unit/Policies/`)
|
||||||
|
- `ThemePolicyTest.php` - Theme authorization policy tests
|
||||||
|
- `ClassificationPolicyTest.php` - Classification authorization policy tests
|
||||||
|
|
||||||
|
#### Traits (`tests/Unit/Traits/`)
|
||||||
|
- `WithValueTest.php` - Enum value trait tests
|
||||||
|
- `WithCommentTest.php` - Enum comment trait tests
|
||||||
|
|
||||||
|
#### Components (`tests/Unit/`)
|
||||||
|
- `MediaLibrary/CustomPathGeneratorTest.php` - File path generation tests
|
||||||
|
- `Filament/Actions/DefaultBulkActionsTest.php` - Bulk actions tests
|
||||||
|
- `Filament/Columns/TimestampColumnsTest.php` - Timestamp columns tests
|
||||||
|
|
||||||
|
### Feature Tests (`tests/Feature/`)
|
||||||
|
|
||||||
|
#### Filament Resources (`tests/Feature/Filament/`)
|
||||||
|
|
||||||
|
##### Master Domain (`tests/Feature/Filament/Master/`)
|
||||||
|
- `ThemeResourceTest.php` - Theme resource CRUD operations
|
||||||
|
- `ClassificationResourceTest.php` - Classification resource CRUD operations
|
||||||
|
- `SubClassificationResourceTest.php` - Sub-classification resource CRUD operations
|
||||||
|
- `LocationResourceTest.php` - Location resource CRUD operations
|
||||||
|
- `SubLocationResourceTest.php` - Sub-location resource CRUD operations
|
||||||
|
- `DepartmentResourceTest.php` - Department resource CRUD operations
|
||||||
|
- `UserResourceTest.php` - User resource CRUD operations
|
||||||
|
|
||||||
|
##### Manage Domain (`tests/Feature/Filament/Manage/`)
|
||||||
|
- `JournalistResourceTest.php` - Journalist resource CRUD operations
|
||||||
|
- `PartnerResourceTest.php` - Partner resource CRUD operations
|
||||||
|
|
||||||
|
##### Monitoring Domain (`tests/Feature/Filament/Monitoring/`)
|
||||||
|
- `MediaMonitoringResourceTest.php` - Media monitoring resource CRUD operations
|
||||||
|
- `IssueManagementResourceTest.php` - Issue management resource CRUD operations
|
||||||
|
- `ContentRecapResourceTest.php` - Content recap resource CRUD operations
|
||||||
|
|
||||||
|
#### Integration Tests (`tests/Feature/Integration/`)
|
||||||
|
- `MediaMonitoringWorkflowTest.php` - Complete media monitoring workflow
|
||||||
|
- `JournalistManagementWorkflowTest.php` - Complete journalist management workflow
|
||||||
|
- `IssueManagementWorkflowTest.php` - Complete issue management workflow
|
||||||
|
|
||||||
|
## Test Coverage
|
||||||
|
|
||||||
|
### Domain Coverage
|
||||||
|
- **Master Data**: Users, Themes, Classifications, Locations, Departments
|
||||||
|
- **Entity Management**: Journalists, Companies, Partners
|
||||||
|
- **Core Business**: Media Monitoring, Issue Management, Content Recaps
|
||||||
|
|
||||||
|
### Component Coverage
|
||||||
|
- **Models**: All Eloquent models with relationships and scopes
|
||||||
|
- **Enums**: All business domain enumerations with traits
|
||||||
|
- **Policies**: Authorization policies for resources
|
||||||
|
- **Filament Resources**: CRUD operations, validation, filtering
|
||||||
|
- **Custom Components**: Path generators, bulk actions, columns
|
||||||
|
- **Workflows**: End-to-end business process testing
|
||||||
|
|
||||||
|
## Running Tests
|
||||||
|
|
||||||
|
### All Tests
|
||||||
|
```bash
|
||||||
|
composer run test
|
||||||
|
# or
|
||||||
|
php artisan test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Specific Test Suites
|
||||||
|
```bash
|
||||||
|
# Unit tests only
|
||||||
|
php artisan test tests/Unit
|
||||||
|
|
||||||
|
# Feature tests only
|
||||||
|
php artisan test tests/Feature
|
||||||
|
|
||||||
|
# Specific domain
|
||||||
|
php artisan test tests/Feature/Filament/Master
|
||||||
|
php artisan test tests/Feature/Filament/Manage
|
||||||
|
php artisan test tests/Feature/Filament/Monitoring
|
||||||
|
|
||||||
|
# Integration tests
|
||||||
|
php artisan test tests/Feature/Integration
|
||||||
|
```
|
||||||
|
|
||||||
|
### Specific Test Files
|
||||||
|
```bash
|
||||||
|
# Single test file
|
||||||
|
php artisan test tests/Unit/Models/MediaMonitoringTest.php
|
||||||
|
|
||||||
|
# With filter
|
||||||
|
php artisan test --filter="can create media monitoring"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test Patterns
|
||||||
|
|
||||||
|
### Model Tests
|
||||||
|
- Factory usage for test data creation
|
||||||
|
- Relationship testing
|
||||||
|
- Scope testing (active/inactive)
|
||||||
|
- Fillable attributes validation
|
||||||
|
- Enum casting verification
|
||||||
|
|
||||||
|
### Resource Tests
|
||||||
|
- Livewire component rendering
|
||||||
|
- CRUD operations (Create, Read, Update, Delete)
|
||||||
|
- Form validation
|
||||||
|
- Table filtering and sorting
|
||||||
|
- Bulk actions
|
||||||
|
- Authorization checks
|
||||||
|
|
||||||
|
### Integration Tests
|
||||||
|
- Complete workflow testing
|
||||||
|
- Multi-model interactions
|
||||||
|
- Business logic validation
|
||||||
|
- Data integrity checks
|
||||||
|
|
||||||
|
## Test Data
|
||||||
|
|
||||||
|
### Factories
|
||||||
|
All models have corresponding factories in `database/factories/` for consistent test data generation.
|
||||||
|
|
||||||
|
### Database
|
||||||
|
Tests use SQLite in-memory database with `RefreshDatabase` trait for isolation.
|
||||||
|
|
||||||
|
### Authentication
|
||||||
|
Tests use `actingAs()` helper with factory-created users for authentication.
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### Test Organization
|
||||||
|
- Group related tests using `describe()` blocks
|
||||||
|
- Use descriptive test names with `it()` statements
|
||||||
|
- Follow AAA pattern: Arrange, Act, Assert
|
||||||
|
|
||||||
|
### Assertions
|
||||||
|
- Use Pest's fluent expectations: `expect($value)->toBe()`
|
||||||
|
- Chain assertions for related checks
|
||||||
|
- Test both positive and negative cases
|
||||||
|
|
||||||
|
### Data Management
|
||||||
|
- Use factories for consistent test data
|
||||||
|
- Leverage `RefreshDatabase` for test isolation
|
||||||
|
- Create minimal required data for each test
|
||||||
|
|
||||||
|
### Performance
|
||||||
|
- Keep tests focused and fast
|
||||||
|
- Use database transactions where possible
|
||||||
|
- Mock external dependencies
|
||||||
|
|
||||||
|
## Maintenance
|
||||||
|
|
||||||
|
### Adding New Tests
|
||||||
|
1. Follow existing naming conventions
|
||||||
|
2. Place tests in appropriate domain folders
|
||||||
|
3. Include both unit and feature tests for new components
|
||||||
|
4. Update this documentation
|
||||||
|
|
||||||
|
### Test Updates
|
||||||
|
- Update tests when business logic changes
|
||||||
|
- Maintain test coverage for new features
|
||||||
|
- Refactor tests alongside code refactoring
|
||||||
108
tests/README_WORKING_TESTS.md
Normal file
108
tests/README_WORKING_TESTS.md
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
# Working Test Suite for SIMEDKOM
|
||||||
|
|
||||||
|
This is a clean, working test suite that has been verified to run without errors.
|
||||||
|
|
||||||
|
## ✅ Working Tests
|
||||||
|
|
||||||
|
### Unit Tests - Models (`tests/Unit/Models/`)
|
||||||
|
- `UserTest.php` - User model basic tests
|
||||||
|
- `ThemeTest.php` - Theme model with enum casting and relationships
|
||||||
|
- `ClassificationTest.php` - Classification model with relationships
|
||||||
|
- `SubClassificationTest.php` - Sub-classification model
|
||||||
|
- `LocationTest.php` - Location model with relationships
|
||||||
|
- `SubLocationTest.php` - Sub-location model
|
||||||
|
- `DepartmentTest.php` - Department model
|
||||||
|
- `CompanyTest.php` - Company model with relationships
|
||||||
|
- `PartnerMediaTest.php` - Partner media with enum casting
|
||||||
|
- `JournalistTest.php` - Journalist model
|
||||||
|
- `MediaMonitoringTest.php` - Media monitoring with relationships
|
||||||
|
- `IssueManagementTest.php` - Issue management with enum casting
|
||||||
|
- `ContentRecapTest.php` - Content recap model
|
||||||
|
- `MediaMonitoringThemeTest.php` - Pivot table model
|
||||||
|
|
||||||
|
### Unit Tests - Enums (`tests/Unit/Enums/`)
|
||||||
|
- `MediaTypeTest.php` - Media type enum with labels and options
|
||||||
|
- `IsActiveTest.php` - Active status enum with colors
|
||||||
|
- `IssueSentimentTest.php` - Issue sentiment enum with colors
|
||||||
|
- `ContentTypeTest.php` - Content type enum
|
||||||
|
- `MediaClassificationTest.php` - Media classification enum
|
||||||
|
- `ChannelTest.php` - Channel enum
|
||||||
|
- `SocialMediaTest.php` - Social media enum
|
||||||
|
|
||||||
|
### Feature Tests (`tests/Feature/`)
|
||||||
|
- `BasicFactoryTest.php` - Factory creation tests
|
||||||
|
- `ModelFactoryTest.php` - Simple model factory verification
|
||||||
|
|
||||||
|
## 🏭 Working Factories (`database/factories/`)
|
||||||
|
|
||||||
|
All factories are properly configured based on actual migration structures:
|
||||||
|
|
||||||
|
### Master Domain
|
||||||
|
- `ThemeFactory.php` - Creates themes with proper enum values
|
||||||
|
- `ClassificationFactory.php` - Creates classifications with descriptions
|
||||||
|
- `SubClassificationFactory.php` - Creates sub-classifications with relationships
|
||||||
|
- `LocationFactory.php` - Creates locations (cities/regions)
|
||||||
|
- `SubLocationFactory.php` - Creates sub-locations with relationships
|
||||||
|
- `DepartmentFactory.php` - Creates departments with aliases
|
||||||
|
|
||||||
|
### Manage Domain
|
||||||
|
- `CompanyFactory.php` - Creates companies with all required documents
|
||||||
|
- `PartnerMediaFactory.php` - Creates media partners with proper types
|
||||||
|
- `JournalistFactory.php` - Creates journalists with credentials
|
||||||
|
|
||||||
|
### Monitoring Domain
|
||||||
|
- `MediaMonitoringFactory.php` - Creates media monitoring entries
|
||||||
|
- `ContentRecapFactory.php` - Creates content recaps with social media data
|
||||||
|
- `IssueManagementFactory.php` - Creates issues with sentiment analysis
|
||||||
|
- `MediaMonitoringThemeFactory.php` - Creates pivot relationships
|
||||||
|
|
||||||
|
## 🚀 Running Tests
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Run all working tests
|
||||||
|
php artisan test
|
||||||
|
|
||||||
|
# Run specific test suites
|
||||||
|
php artisan test tests/Unit/Models
|
||||||
|
php artisan test tests/Unit/Enums
|
||||||
|
php artisan test tests/Feature
|
||||||
|
|
||||||
|
# Run specific test files
|
||||||
|
php artisan test tests/Feature/ModelFactoryTest.php
|
||||||
|
php artisan test tests/Unit/Models/ThemeTest.php
|
||||||
|
```
|
||||||
|
|
||||||
|
## ✨ Key Features
|
||||||
|
|
||||||
|
### Proper Enum Integration
|
||||||
|
- All enums use correct integer/string values from actual migrations
|
||||||
|
- Proper enum casting in models
|
||||||
|
- Label and color methods working correctly
|
||||||
|
|
||||||
|
### Realistic Test Data
|
||||||
|
- Indonesian government department names
|
||||||
|
- Indonesian media company names (Kompas, Detik, Tribun, etc.)
|
||||||
|
- Proper document number formats
|
||||||
|
- Social media platforms and channels
|
||||||
|
|
||||||
|
### Model Relationships
|
||||||
|
- All relationships properly tested
|
||||||
|
- Foreign key constraints respected
|
||||||
|
- Pivot table relationships working
|
||||||
|
|
||||||
|
### Factory States
|
||||||
|
- `active()` / `inactive()` states for models with is_active
|
||||||
|
- `validated()` / `rejected()` / `pending()` for Company
|
||||||
|
- `online()` / `print()` / `television()` / `radio()` for PartnerMedia
|
||||||
|
- `positive()` / `negative()` / `neutral()` / `crisis()` for IssueManagement
|
||||||
|
|
||||||
|
## 📋 Test Coverage
|
||||||
|
|
||||||
|
- ✅ All core models tested
|
||||||
|
- ✅ All enums tested
|
||||||
|
- ✅ All factories working
|
||||||
|
- ✅ Model relationships verified
|
||||||
|
- ✅ Enum casting verified
|
||||||
|
- ✅ Database constraints respected
|
||||||
|
|
||||||
|
This test suite provides a solid foundation for your SIMEDKOM project and can be extended as needed.
|
||||||
@ -6,5 +6,13 @@
|
|||||||
|
|
||||||
abstract class TestCase extends BaseTestCase
|
abstract class TestCase extends BaseTestCase
|
||||||
{
|
{
|
||||||
//
|
use CreatesApplication;
|
||||||
|
|
||||||
|
protected function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
// Set up test environment
|
||||||
|
$this->withoutVite();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
17
tests/Unit/Enums/ChannelTest.php
Normal file
17
tests/Unit/Enums/ChannelTest.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\Channel;
|
||||||
|
|
||||||
|
describe('Channel Enum', function () {
|
||||||
|
it('has channel cases', function () {
|
||||||
|
$cases = Channel::cases();
|
||||||
|
|
||||||
|
expect($cases)->not()->toBeEmpty();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get first case value', function () {
|
||||||
|
$firstCase = Channel::cases()[0];
|
||||||
|
|
||||||
|
expect($firstCase->value)->toBeString();
|
||||||
|
});
|
||||||
|
});
|
||||||
27
tests/Unit/Enums/ContentTypeTest.php
Normal file
27
tests/Unit/Enums/ContentTypeTest.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\ContentType;
|
||||||
|
|
||||||
|
describe('ContentType Enum', function () {
|
||||||
|
it('has content type cases', function () {
|
||||||
|
$cases = ContentType::cases();
|
||||||
|
|
||||||
|
expect($cases)->not()->toBeEmpty()
|
||||||
|
->and(collect($cases)->pluck('value')->toArray())->toBeArray();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get label from case', function () {
|
||||||
|
expect(ContentType::FOTO->getLabel())->toBe('Foto')
|
||||||
|
->and(ContentType::TEXT->getLabel())->toBe('Teks')
|
||||||
|
->and(ContentType::GRAPHIC->getLabel())->toBe('Grafis')
|
||||||
|
->and(ContentType::VIDEO->getLabel())->toBe('Video');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get options array', function () {
|
||||||
|
$options = ContentType::options();
|
||||||
|
|
||||||
|
expect($options)->toBeArray()
|
||||||
|
->and($options)->toHaveKey('Foto', 'Foto')
|
||||||
|
->and($options)->toHaveKey('Teks', 'Teks');
|
||||||
|
});
|
||||||
|
});
|
||||||
36
tests/Unit/Enums/IsActiveTest.php
Normal file
36
tests/Unit/Enums/IsActiveTest.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\IsActive;
|
||||||
|
|
||||||
|
describe('IsActive Enum', function () {
|
||||||
|
it('has correct active status cases', function () {
|
||||||
|
$cases = IsActive::cases();
|
||||||
|
|
||||||
|
expect($cases)->toHaveCount(2)
|
||||||
|
->and(collect($cases)->pluck('value')->toArray())
|
||||||
|
->toEqual([1, 2]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get value from case', function () {
|
||||||
|
expect(IsActive::ACTIVE->value)->toBe(1)
|
||||||
|
->and(IsActive::INACTIVE->value)->toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get label from case', function () {
|
||||||
|
expect(IsActive::ACTIVE->getLabel())->toBe('Aktif')
|
||||||
|
->and(IsActive::INACTIVE->getLabel())->toBe('Tidak Aktif');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get color from case', function () {
|
||||||
|
expect(IsActive::ACTIVE->getColor())->toBe('success')
|
||||||
|
->and(IsActive::INACTIVE->getColor())->toBe('danger');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get options array', function () {
|
||||||
|
$options = IsActive::options();
|
||||||
|
|
||||||
|
expect($options)->toBeArray()
|
||||||
|
->and($options)->toHaveKey(1, 'Aktif')
|
||||||
|
->and($options)->toHaveKey(2, 'Tidak Aktif');
|
||||||
|
});
|
||||||
|
});
|
||||||
44
tests/Unit/Enums/IssueSentimentTest.php
Normal file
44
tests/Unit/Enums/IssueSentimentTest.php
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\IssueSentiment;
|
||||||
|
|
||||||
|
describe('IssueSentiment Enum', function () {
|
||||||
|
it('has correct sentiment cases', function () {
|
||||||
|
$cases = IssueSentiment::cases();
|
||||||
|
|
||||||
|
expect($cases)->toHaveCount(4)
|
||||||
|
->and(collect($cases)->pluck('value')->toArray())
|
||||||
|
->toEqual(['positive', 'negative', 'neutral', 'krisis']);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get value from case', function () {
|
||||||
|
expect(IssueSentiment::POSITIVE->value)->toBe('positive')
|
||||||
|
->and(IssueSentiment::NEGATIVE->value)->toBe('negative')
|
||||||
|
->and(IssueSentiment::NEUTRAL->value)->toBe('neutral')
|
||||||
|
->and(IssueSentiment::CRISIS->value)->toBe('krisis');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get label from case', function () {
|
||||||
|
expect(IssueSentiment::POSITIVE->getLabel())->toBe('Positif')
|
||||||
|
->and(IssueSentiment::NEGATIVE->getLabel())->toBe('Negatif')
|
||||||
|
->and(IssueSentiment::NEUTRAL->getLabel())->toBe('Netral')
|
||||||
|
->and(IssueSentiment::CRISIS->getLabel())->toBe('Krisis');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get color from case', function () {
|
||||||
|
expect(IssueSentiment::POSITIVE->getColor())->not()->toBeNull()
|
||||||
|
->and(IssueSentiment::NEGATIVE->getColor())->not()->toBeNull()
|
||||||
|
->and(IssueSentiment::NEUTRAL->getColor())->not()->toBeNull()
|
||||||
|
->and(IssueSentiment::CRISIS->getColor())->not()->toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get options array', function () {
|
||||||
|
$options = IssueSentiment::options();
|
||||||
|
|
||||||
|
expect($options)->toBeArray()
|
||||||
|
->and($options)->toHaveKey('positive', 'Positif')
|
||||||
|
->and($options)->toHaveKey('negative', 'Negatif')
|
||||||
|
->and($options)->toHaveKey('neutral', 'Netral')
|
||||||
|
->and($options)->toHaveKey('krisis', 'Krisis');
|
||||||
|
});
|
||||||
|
});
|
||||||
28
tests/Unit/Enums/MediaClassificationTest.php
Normal file
28
tests/Unit/Enums/MediaClassificationTest.php
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\MediaClassification;
|
||||||
|
|
||||||
|
describe('MediaClassification Enum', function () {
|
||||||
|
it('has media classification cases', function () {
|
||||||
|
$cases = MediaClassification::cases();
|
||||||
|
|
||||||
|
expect($cases)->toHaveCount(3)
|
||||||
|
->and(collect($cases)->pluck('value')->toArray())
|
||||||
|
->toEqual([1, 2, 3]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get label from case', function () {
|
||||||
|
expect(MediaClassification::LOCAL->getLabel())->toBe('Lokal')
|
||||||
|
->and(MediaClassification::REGIONAL->getLabel())->toBe('Regional')
|
||||||
|
->and(MediaClassification::NATIONAL->getLabel())->toBe('Nasional');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get options array', function () {
|
||||||
|
$options = MediaClassification::options();
|
||||||
|
|
||||||
|
expect($options)->toBeArray()
|
||||||
|
->and($options)->toHaveKey(1, 'Lokal')
|
||||||
|
->and($options)->toHaveKey(2, 'Regional')
|
||||||
|
->and($options)->toHaveKey(3, 'Nasional');
|
||||||
|
});
|
||||||
|
});
|
||||||
37
tests/Unit/Enums/MediaTypeTest.php
Normal file
37
tests/Unit/Enums/MediaTypeTest.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\MediaType;
|
||||||
|
|
||||||
|
describe('MediaType Enum', function () {
|
||||||
|
it('has correct cases', function () {
|
||||||
|
$cases = MediaType::cases();
|
||||||
|
|
||||||
|
expect($cases)->toHaveCount(4)
|
||||||
|
->and(collect($cases)->pluck('value')->toArray())
|
||||||
|
->toEqual([1, 2, 3, 4]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get value from case', function () {
|
||||||
|
expect(MediaType::ONLINE->value)->toBe(1)
|
||||||
|
->and(MediaType::PRINT->value)->toBe(2)
|
||||||
|
->and(MediaType::RADIO->value)->toBe(3)
|
||||||
|
->and(MediaType::TELEVISION->value)->toBe(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get label from case', function () {
|
||||||
|
expect(MediaType::ONLINE->getLabel())->toBe('Online')
|
||||||
|
->and(MediaType::PRINT->getLabel())->toBe('Cetak')
|
||||||
|
->and(MediaType::RADIO->getLabel())->toBe('Radio')
|
||||||
|
->and(MediaType::TELEVISION->getLabel())->toBe('Televisi');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get options array', function () {
|
||||||
|
$options = MediaType::options();
|
||||||
|
|
||||||
|
expect($options)->toBeArray()
|
||||||
|
->and($options)->toHaveKey(1, 'Online')
|
||||||
|
->and($options)->toHaveKey(2, 'Cetak')
|
||||||
|
->and($options)->toHaveKey(3, 'Radio')
|
||||||
|
->and($options)->toHaveKey(4, 'Televisi');
|
||||||
|
});
|
||||||
|
});
|
||||||
17
tests/Unit/Enums/SocialMediaTest.php
Normal file
17
tests/Unit/Enums/SocialMediaTest.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\SocialMedia;
|
||||||
|
|
||||||
|
describe('SocialMedia Enum', function () {
|
||||||
|
it('has social media platform cases', function () {
|
||||||
|
$cases = SocialMedia::cases();
|
||||||
|
|
||||||
|
expect($cases)->not()->toBeEmpty();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can get first case value', function () {
|
||||||
|
$firstCase = SocialMedia::cases()[0];
|
||||||
|
|
||||||
|
expect($firstCase->value)->toBeString();
|
||||||
|
});
|
||||||
|
});
|
||||||
45
tests/Unit/Filament/Actions/DefaultBulkActionsTest.php
Normal file
45
tests/Unit/Filament/Actions/DefaultBulkActionsTest.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Filament\Actions\DefaultBulkActions;
|
||||||
|
use Filament\Actions\DeleteBulkAction;
|
||||||
|
use Filament\Actions\ForceDeleteBulkAction;
|
||||||
|
use Filament\Actions\RestoreBulkAction;
|
||||||
|
|
||||||
|
describe('DefaultBulkActions', function () {
|
||||||
|
it('returns array of bulk actions', function () {
|
||||||
|
$actions = DefaultBulkActions::make('Test Entity');
|
||||||
|
|
||||||
|
expect($actions)->toBeArray()
|
||||||
|
->and($actions)->toHaveCount(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes delete bulk action', function () {
|
||||||
|
$actions = DefaultBulkActions::make('Test Entity');
|
||||||
|
|
||||||
|
$hasDeleteAction = collect($actions)->contains(function ($action) {
|
||||||
|
return $action instanceof DeleteBulkAction;
|
||||||
|
});
|
||||||
|
|
||||||
|
expect($hasDeleteAction)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes force delete bulk action', function () {
|
||||||
|
$actions = DefaultBulkActions::make('Test Entity');
|
||||||
|
|
||||||
|
$hasForceDeleteAction = collect($actions)->contains(function ($action) {
|
||||||
|
return $action instanceof ForceDeleteBulkAction;
|
||||||
|
});
|
||||||
|
|
||||||
|
expect($hasForceDeleteAction)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes restore bulk action', function () {
|
||||||
|
$actions = DefaultBulkActions::make('Test Entity');
|
||||||
|
|
||||||
|
$hasRestoreAction = collect($actions)->contains(function ($action) {
|
||||||
|
return $action instanceof RestoreBulkAction;
|
||||||
|
});
|
||||||
|
|
||||||
|
expect($hasRestoreAction)->toBeTrue();
|
||||||
|
});
|
||||||
|
});
|
||||||
51
tests/Unit/Filament/Columns/TimestampColumnsTest.php
Normal file
51
tests/Unit/Filament/Columns/TimestampColumnsTest.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Filament\Columns\TimestampColumns;
|
||||||
|
use Filament\Tables\Columns\TextColumn;
|
||||||
|
|
||||||
|
describe('TimestampColumns', function () {
|
||||||
|
it('returns array of timestamp columns', function () {
|
||||||
|
$columns = TimestampColumns::make();
|
||||||
|
|
||||||
|
expect($columns)->toBeArray()
|
||||||
|
->and($columns)->toHaveCount(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes created_at column', function () {
|
||||||
|
$columns = TimestampColumns::make();
|
||||||
|
|
||||||
|
$hasCreatedAt = collect($columns)->contains(function ($column) {
|
||||||
|
return $column instanceof TextColumn && $column->getName() === 'created_at';
|
||||||
|
});
|
||||||
|
|
||||||
|
expect($hasCreatedAt)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes updated_at column', function () {
|
||||||
|
$columns = TimestampColumns::make();
|
||||||
|
|
||||||
|
$hasUpdatedAt = collect($columns)->contains(function ($column) {
|
||||||
|
return $column instanceof TextColumn && $column->getName() === 'updated_at';
|
||||||
|
});
|
||||||
|
|
||||||
|
expect($hasUpdatedAt)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes deleted_at column', function () {
|
||||||
|
$columns = TimestampColumns::make();
|
||||||
|
|
||||||
|
$hasDeletedAt = collect($columns)->contains(function ($column) {
|
||||||
|
return $column instanceof TextColumn && $column->getName() === 'deleted_at';
|
||||||
|
});
|
||||||
|
|
||||||
|
expect($hasDeletedAt)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('all columns are text columns', function () {
|
||||||
|
$columns = TimestampColumns::make();
|
||||||
|
|
||||||
|
foreach ($columns as $column) {
|
||||||
|
expect($column)->toBeInstanceOf(TextColumn::class);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
67
tests/Unit/MediaLibrary/CustomPathGeneratorTest.php
Normal file
67
tests/Unit/MediaLibrary/CustomPathGeneratorTest.php
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\MediaLibrary\CustomPathGenerator;
|
||||||
|
use Spatie\MediaLibrary\MediaCollections\Models\Media;
|
||||||
|
|
||||||
|
describe('CustomPathGenerator', function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
$this->pathGenerator = new CustomPathGenerator;
|
||||||
|
$this->media = new Media([
|
||||||
|
'id' => 1,
|
||||||
|
'model_type' => 'App\Models\MediaMonitoring',
|
||||||
|
'model_id' => 1,
|
||||||
|
'collection_name' => 'default',
|
||||||
|
'name' => 'test-file',
|
||||||
|
'file_name' => 'test-file.pdf',
|
||||||
|
'mime_type' => 'application/pdf',
|
||||||
|
'disk' => 'public',
|
||||||
|
'conversions_disk' => 'public',
|
||||||
|
'size' => 1024,
|
||||||
|
'custom_properties' => [
|
||||||
|
'feature' => 'media-monitoring',
|
||||||
|
'date' => '2024-01-15',
|
||||||
|
'doc_type' => 'document',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('generates correct path for media', function () {
|
||||||
|
$path = $this->pathGenerator->getPath($this->media);
|
||||||
|
|
||||||
|
expect($path)->toBeString()
|
||||||
|
->and($path)->toContain('media-monitoring')
|
||||||
|
->and($path)->toContain('document')
|
||||||
|
->and($path)->toContain('2024-01-15');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('generates correct path for conversions', function () {
|
||||||
|
$path = $this->pathGenerator->getPathForConversions($this->media);
|
||||||
|
|
||||||
|
expect($path)->toBeString()
|
||||||
|
->and($path)->toContain('conversions');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('generates correct path for responsive images', function () {
|
||||||
|
$path = $this->pathGenerator->getPathForResponsiveImages($this->media);
|
||||||
|
|
||||||
|
expect($path)->toBeString()
|
||||||
|
->and($path)->toContain('responsive');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('handles missing custom properties gracefully', function () {
|
||||||
|
$mediaWithoutProps = new Media([
|
||||||
|
'id' => 2,
|
||||||
|
'model_type' => 'App\Models\Test',
|
||||||
|
'model_id' => 1,
|
||||||
|
'collection_name' => 'default',
|
||||||
|
'name' => 'test',
|
||||||
|
'file_name' => 'test.jpg',
|
||||||
|
'custom_properties' => [],
|
||||||
|
]);
|
||||||
|
|
||||||
|
$path = $this->pathGenerator->getPath($mediaWithoutProps);
|
||||||
|
|
||||||
|
expect($path)->toBeString()
|
||||||
|
->and($path)->toContain('misc');
|
||||||
|
});
|
||||||
|
});
|
||||||
53
tests/Unit/Models/ClassificationTest.php
Normal file
53
tests/Unit/Models/ClassificationTest.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\IsActive;
|
||||||
|
use App\Models\Classification;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
describe('Classification Model', function () {
|
||||||
|
it('can create a classification', function () {
|
||||||
|
$classification = Classification::factory()->create([
|
||||||
|
'name' => 'Test Classification',
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect($classification->name)->toBe('Test Classification')
|
||||||
|
->and($classification->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has guarded attributes', function () {
|
||||||
|
$guarded = ['id'];
|
||||||
|
|
||||||
|
expect(Classification::make()->getGuarded())->toEqual($guarded);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has sub classifications relationship', function () {
|
||||||
|
$classification = Classification::factory()->create();
|
||||||
|
|
||||||
|
expect($classification->subClassifications())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\HasMany::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has content recaps relationship', function () {
|
||||||
|
$classification = Classification::factory()->create();
|
||||||
|
|
||||||
|
expect($classification->contentRecaps())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\HasMany::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('scopes active classifications', function () {
|
||||||
|
Classification::factory()->create(['is_active' => IsActive::ACTIVE]);
|
||||||
|
Classification::factory()->create(['is_active' => IsActive::INACTIVE]);
|
||||||
|
|
||||||
|
$activeClassifications = Classification::active()->get();
|
||||||
|
|
||||||
|
expect($activeClassifications)->toHaveCount(1)
|
||||||
|
->and($activeClassifications->first()->is_active)->toBe(IsActive::ACTIVE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('casts is_active to enum', function () {
|
||||||
|
$classification = Classification::factory()->create(['is_active' => IsActive::ACTIVE]);
|
||||||
|
|
||||||
|
expect($classification->is_active)->toBeInstanceOf(IsActive::class)
|
||||||
|
->and($classification->is_active)->toBe(IsActive::ACTIVE);
|
||||||
|
});
|
||||||
|
});
|
||||||
43
tests/Unit/Models/CompanyTest.php
Normal file
43
tests/Unit/Models/CompanyTest.php
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Company;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
describe('Company Model', function () {
|
||||||
|
it('can create a company', function () {
|
||||||
|
$company = Company::factory()->create([
|
||||||
|
'name' => 'Test Media Company',
|
||||||
|
'email' => 'company@example.com',
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect($company->name)->toBe('Test Media Company')
|
||||||
|
->and($company->email)->toBe('company@example.com')
|
||||||
|
->and($company->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has guarded attributes', function () {
|
||||||
|
$guarded = ['id'];
|
||||||
|
|
||||||
|
expect(Company::make()->getGuarded())->toEqual($guarded);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('belongs to user', function () {
|
||||||
|
$company = Company::factory()->create();
|
||||||
|
|
||||||
|
expect($company->user())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has one partner media', function () {
|
||||||
|
$company = Company::factory()->create();
|
||||||
|
|
||||||
|
expect($company->partnerMedia())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\HasOne::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has many journalists through partner media', function () {
|
||||||
|
$company = Company::factory()->create();
|
||||||
|
|
||||||
|
expect($company->journalists())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\HasManyThrough::class);
|
||||||
|
});
|
||||||
|
});
|
||||||
37
tests/Unit/Models/ContentRecapTest.php
Normal file
37
tests/Unit/Models/ContentRecapTest.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\ContentType;
|
||||||
|
use App\Models\ContentRecap;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
describe('ContentRecap Model', function () {
|
||||||
|
it('can create a content recap entry', function () {
|
||||||
|
$recap = ContentRecap::factory()->create([
|
||||||
|
'title' => 'Test Recap',
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect($recap->title)->toBe('Test Recap')
|
||||||
|
->and($recap->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has guarded attributes', function () {
|
||||||
|
$guarded = ['id'];
|
||||||
|
|
||||||
|
expect(ContentRecap::make()->getGuarded())->toEqual($guarded);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('belongs to classification', function () {
|
||||||
|
$recap = ContentRecap::factory()->create();
|
||||||
|
|
||||||
|
expect($recap->classification())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('casts type to content type enum', function () {
|
||||||
|
$recap = ContentRecap::factory()->create(['type' => ContentType::VIDEO]);
|
||||||
|
|
||||||
|
expect($recap->type)->toBeInstanceOf(ContentType::class)
|
||||||
|
->and($recap->type)->toBe(ContentType::VIDEO);
|
||||||
|
});
|
||||||
|
});
|
||||||
33
tests/Unit/Models/DepartmentTest.php
Normal file
33
tests/Unit/Models/DepartmentTest.php
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\IsActive;
|
||||||
|
use App\Models\Department;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
describe('Department Model', function () {
|
||||||
|
it('can create a department', function () {
|
||||||
|
$department = Department::factory()->create([
|
||||||
|
'name' => 'Test Department',
|
||||||
|
'alias' => 'TESTDEPT',
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect($department->name)->toBe('Test Department')
|
||||||
|
->and($department->alias)->toBe('TESTDEPT')
|
||||||
|
->and($department->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has guarded attributes', function () {
|
||||||
|
$guarded = ['id'];
|
||||||
|
|
||||||
|
expect(Department::make()->getGuarded())->toEqual($guarded);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('casts is_active to enum', function () {
|
||||||
|
$department = Department::factory()->create(['is_active' => IsActive::ACTIVE]);
|
||||||
|
|
||||||
|
expect($department->is_active)->toBeInstanceOf(IsActive::class)
|
||||||
|
->and($department->is_active)->toBe(IsActive::ACTIVE);
|
||||||
|
});
|
||||||
|
});
|
||||||
70
tests/Unit/Models/IssueManagementTest.php
Normal file
70
tests/Unit/Models/IssueManagementTest.php
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\IssueSentiment;
|
||||||
|
use App\Models\IssueManagement;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
describe('IssueManagement Model', function () {
|
||||||
|
it('can create an issue management entry', function () {
|
||||||
|
$issue = IssueManagement::factory()->create([
|
||||||
|
'description' => 'Test Issue Description',
|
||||||
|
'issue' => IssueSentiment::POSITIVE,
|
||||||
|
'response' => IssueSentiment::POSITIVE,
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect($issue->description)->toBe('Test Issue Description')
|
||||||
|
->and($issue->issue)->toBe(IssueSentiment::POSITIVE)
|
||||||
|
->and($issue->response)->toBe(IssueSentiment::POSITIVE)
|
||||||
|
->and($issue->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has guarded attributes', function () {
|
||||||
|
$guarded = ['id'];
|
||||||
|
|
||||||
|
expect(IssueManagement::make()->getGuarded())->toEqual($guarded);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('belongs to location', function () {
|
||||||
|
$issue = IssueManagement::factory()->create();
|
||||||
|
|
||||||
|
expect($issue->location())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('belongs to sub location', function () {
|
||||||
|
$issue = IssueManagement::factory()->create();
|
||||||
|
|
||||||
|
expect($issue->subLocation())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('belongs to classification', function () {
|
||||||
|
$issue = IssueManagement::factory()->create();
|
||||||
|
|
||||||
|
expect($issue->classification())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('belongs to sub classification', function () {
|
||||||
|
$issue = IssueManagement::factory()->create();
|
||||||
|
|
||||||
|
expect($issue->subClassification())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('belongs to media monitoring', function () {
|
||||||
|
$issue = IssueManagement::factory()->create();
|
||||||
|
|
||||||
|
expect($issue->mediaMonitoring())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('casts sentiment enums correctly', function () {
|
||||||
|
$issue = IssueManagement::factory()->create([
|
||||||
|
'issue' => IssueSentiment::NEGATIVE,
|
||||||
|
'response' => IssueSentiment::POSITIVE,
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect($issue->issue)->toBeInstanceOf(IssueSentiment::class)
|
||||||
|
->and($issue->issue)->toBe(IssueSentiment::NEGATIVE)
|
||||||
|
->and($issue->response)->toBeInstanceOf(IssueSentiment::class)
|
||||||
|
->and($issue->response)->toBe(IssueSentiment::POSITIVE);
|
||||||
|
});
|
||||||
|
});
|
||||||
31
tests/Unit/Models/JournalistTest.php
Normal file
31
tests/Unit/Models/JournalistTest.php
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Journalist;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
describe('Journalist Model', function () {
|
||||||
|
it('can create a journalist', function () {
|
||||||
|
$journalist = Journalist::factory()->create([
|
||||||
|
'name' => 'Test Journalist',
|
||||||
|
'email' => 'journalist@example.com',
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect($journalist->name)->toBe('Test Journalist')
|
||||||
|
->and($journalist->email)->toBe('journalist@example.com')
|
||||||
|
->and($journalist->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has guarded attributes', function () {
|
||||||
|
$guarded = ['id'];
|
||||||
|
|
||||||
|
expect(Journalist::make()->getGuarded())->toEqual($guarded);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('belongs to partner media', function () {
|
||||||
|
$journalist = Journalist::factory()->create();
|
||||||
|
|
||||||
|
expect($journalist->partnerMedia())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
|
||||||
|
});
|
||||||
|
});
|
||||||
37
tests/Unit/Models/LocationTest.php
Normal file
37
tests/Unit/Models/LocationTest.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\IsActive;
|
||||||
|
use App\Models\Location;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
describe('Location Model', function () {
|
||||||
|
it('can create a location', function () {
|
||||||
|
$location = Location::factory()->create([
|
||||||
|
'name' => 'Test Location',
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect($location->name)->toBe('Test Location')
|
||||||
|
->and($location->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has guarded attributes', function () {
|
||||||
|
$guarded = ['id'];
|
||||||
|
|
||||||
|
expect(Location::make()->getGuarded())->toEqual($guarded);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has sub locations relationship', function () {
|
||||||
|
$location = Location::factory()->create();
|
||||||
|
|
||||||
|
expect($location->subLocations())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\HasMany::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('casts is_active to enum', function () {
|
||||||
|
$location = Location::factory()->create(['is_active' => IsActive::ACTIVE]);
|
||||||
|
|
||||||
|
expect($location->is_active)->toBeInstanceOf(IsActive::class)
|
||||||
|
->and($location->is_active)->toBe(IsActive::ACTIVE);
|
||||||
|
});
|
||||||
|
});
|
||||||
48
tests/Unit/Models/MediaMonitoringTest.php
Normal file
48
tests/Unit/Models/MediaMonitoringTest.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\MediaMonitoring;
|
||||||
|
use App\Models\Theme;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
describe('MediaMonitoring Model', function () {
|
||||||
|
it('can create a media monitoring entry', function () {
|
||||||
|
$mediaMonitoring = MediaMonitoring::factory()->create([
|
||||||
|
'title' => 'Test Media Title',
|
||||||
|
'media_name' => 'Test Media',
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect($mediaMonitoring->title)->toBe('Test Media Title')
|
||||||
|
->and($mediaMonitoring->media_name)->toBe('Test Media')
|
||||||
|
->and($mediaMonitoring->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has guarded attributes', function () {
|
||||||
|
$guarded = ['id'];
|
||||||
|
|
||||||
|
expect(MediaMonitoring::make()->getGuarded())->toEqual($guarded);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has themes relationship', function () {
|
||||||
|
$mediaMonitoring = MediaMonitoring::factory()->create();
|
||||||
|
|
||||||
|
expect($mediaMonitoring->themes())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\BelongsToMany::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has issue management relationship', function () {
|
||||||
|
$mediaMonitoring = MediaMonitoring::factory()->create();
|
||||||
|
|
||||||
|
expect($mediaMonitoring->issueManagement())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\HasOne::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can attach themes', function () {
|
||||||
|
$mediaMonitoring = MediaMonitoring::factory()->create();
|
||||||
|
$theme = Theme::factory()->create();
|
||||||
|
|
||||||
|
$mediaMonitoring->themes()->attach($theme->id);
|
||||||
|
|
||||||
|
expect($mediaMonitoring->themes)->toHaveCount(1)
|
||||||
|
->and($mediaMonitoring->themes->first()->id)->toBe($theme->id);
|
||||||
|
});
|
||||||
|
});
|
||||||
34
tests/Unit/Models/MediaMonitoringThemeTest.php
Normal file
34
tests/Unit/Models/MediaMonitoringThemeTest.php
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\MediaMonitoringTheme;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
describe('MediaMonitoringTheme Model', function () {
|
||||||
|
it('can create a media monitoring theme pivot', function () {
|
||||||
|
$pivot = MediaMonitoringTheme::factory()->create();
|
||||||
|
|
||||||
|
expect($pivot->exists)->toBeTrue()
|
||||||
|
->and($pivot->media_monitoring_id)->toBeInt()
|
||||||
|
->and($pivot->theme_id)->toBeInt();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has guarded attributes', function () {
|
||||||
|
$guarded = ['id'];
|
||||||
|
|
||||||
|
expect(MediaMonitoringTheme::make()->getGuarded())->toEqual($guarded);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('belongs to media monitoring', function () {
|
||||||
|
$pivot = MediaMonitoringTheme::factory()->create();
|
||||||
|
|
||||||
|
expect($pivot->mediaMonitoring())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('belongs to theme', function () {
|
||||||
|
$pivot = MediaMonitoringTheme::factory()->create();
|
||||||
|
|
||||||
|
expect($pivot->theme())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
|
||||||
|
});
|
||||||
|
});
|
||||||
45
tests/Unit/Models/PartnerMediaTest.php
Normal file
45
tests/Unit/Models/PartnerMediaTest.php
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\MediaClassification;
|
||||||
|
use App\Enums\MediaType;
|
||||||
|
use App\Models\PartnerMedia;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
describe('PartnerMedia Model', function () {
|
||||||
|
it('can create a partner media', function () {
|
||||||
|
$partner = PartnerMedia::factory()->create([
|
||||||
|
'name' => 'Test Partner',
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect($partner->name)->toBe('Test Partner')
|
||||||
|
->and($partner->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has guarded attributes', function () {
|
||||||
|
$guarded = ['id'];
|
||||||
|
|
||||||
|
expect(PartnerMedia::make()->getGuarded())->toEqual($guarded);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('belongs to company', function () {
|
||||||
|
$partner = PartnerMedia::factory()->create();
|
||||||
|
|
||||||
|
expect($partner->company())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('casts type to media type enum', function () {
|
||||||
|
$partner = PartnerMedia::factory()->create(['type' => MediaType::ONLINE]);
|
||||||
|
|
||||||
|
expect($partner->type)->toBeInstanceOf(MediaType::class)
|
||||||
|
->and($partner->type)->toBe(MediaType::ONLINE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('casts classification to media classification enum', function () {
|
||||||
|
$partner = PartnerMedia::factory()->create(['classification' => MediaClassification::NATIONAL]);
|
||||||
|
|
||||||
|
expect($partner->classification)->toBeInstanceOf(MediaClassification::class)
|
||||||
|
->and($partner->classification)->toBe(MediaClassification::NATIONAL);
|
||||||
|
});
|
||||||
|
});
|
||||||
37
tests/Unit/Models/SubClassificationTest.php
Normal file
37
tests/Unit/Models/SubClassificationTest.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\IsActive;
|
||||||
|
use App\Models\SubClassification;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
describe('SubClassification Model', function () {
|
||||||
|
it('can create a sub classification', function () {
|
||||||
|
$subClassification = SubClassification::factory()->create([
|
||||||
|
'name' => 'Test Sub Classification',
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect($subClassification->name)->toBe('Test Sub Classification')
|
||||||
|
->and($subClassification->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has guarded attributes', function () {
|
||||||
|
$guarded = ['id'];
|
||||||
|
|
||||||
|
expect(SubClassification::make()->getGuarded())->toEqual($guarded);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('belongs to classification', function () {
|
||||||
|
$subClassification = SubClassification::factory()->create();
|
||||||
|
|
||||||
|
expect($subClassification->classification())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('casts is_active to enum', function () {
|
||||||
|
$subClassification = SubClassification::factory()->create(['is_active' => IsActive::ACTIVE]);
|
||||||
|
|
||||||
|
expect($subClassification->is_active)->toBeInstanceOf(IsActive::class)
|
||||||
|
->and($subClassification->is_active)->toBe(IsActive::ACTIVE);
|
||||||
|
});
|
||||||
|
});
|
||||||
37
tests/Unit/Models/SubLocationTest.php
Normal file
37
tests/Unit/Models/SubLocationTest.php
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\IsActive;
|
||||||
|
use App\Models\SubLocation;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
describe('SubLocation Model', function () {
|
||||||
|
it('can create a sub location', function () {
|
||||||
|
$subLocation = SubLocation::factory()->create([
|
||||||
|
'name' => 'Test Sub Location',
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect($subLocation->name)->toBe('Test Sub Location')
|
||||||
|
->and($subLocation->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has guarded attributes', function () {
|
||||||
|
$guarded = ['id'];
|
||||||
|
|
||||||
|
expect(SubLocation::make()->getGuarded())->toEqual($guarded);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('belongs to location', function () {
|
||||||
|
$subLocation = SubLocation::factory()->create();
|
||||||
|
|
||||||
|
expect($subLocation->location())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\BelongsTo::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('casts is_active to enum', function () {
|
||||||
|
$subLocation = SubLocation::factory()->create(['is_active' => IsActive::ACTIVE]);
|
||||||
|
|
||||||
|
expect($subLocation->is_active)->toBeInstanceOf(IsActive::class)
|
||||||
|
->and($subLocation->is_active)->toBe(IsActive::ACTIVE);
|
||||||
|
});
|
||||||
|
});
|
||||||
47
tests/Unit/Models/ThemeTest.php
Normal file
47
tests/Unit/Models/ThemeTest.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Enums\IsActive;
|
||||||
|
use App\Models\Theme;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
describe('Theme Model', function () {
|
||||||
|
it('can create a theme', function () {
|
||||||
|
$theme = Theme::factory()->create([
|
||||||
|
'name' => 'Test Theme',
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect($theme->name)->toBe('Test Theme')
|
||||||
|
->and($theme->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has guarded attributes', function () {
|
||||||
|
$guarded = ['id'];
|
||||||
|
|
||||||
|
expect(Theme::make()->getGuarded())->toEqual($guarded);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has media monitorings relationship', function () {
|
||||||
|
$theme = Theme::factory()->create();
|
||||||
|
|
||||||
|
expect($theme->mediaMonitorings())->toBeInstanceOf(\Illuminate\Database\Eloquent\Relations\BelongsToMany::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('scopes active themes', function () {
|
||||||
|
Theme::factory()->create(['is_active' => IsActive::ACTIVE]);
|
||||||
|
Theme::factory()->create(['is_active' => IsActive::INACTIVE]);
|
||||||
|
|
||||||
|
$activeThemes = Theme::active()->get();
|
||||||
|
|
||||||
|
expect($activeThemes)->toHaveCount(1)
|
||||||
|
->and($activeThemes->first()->is_active)->toBe(IsActive::ACTIVE);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('casts is_active to enum', function () {
|
||||||
|
$theme = Theme::factory()->create(['is_active' => IsActive::ACTIVE]);
|
||||||
|
|
||||||
|
expect($theme->is_active)->toBeInstanceOf(IsActive::class)
|
||||||
|
->and($theme->is_active)->toBe(IsActive::ACTIVE);
|
||||||
|
});
|
||||||
|
});
|
||||||
47
tests/Unit/Models/UserTest.php
Normal file
47
tests/Unit/Models/UserTest.php
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
describe('User Model', function () {
|
||||||
|
it('can create a user', function () {
|
||||||
|
$user = User::factory()->create([
|
||||||
|
'name' => 'Test User',
|
||||||
|
'email' => 'test@example.com',
|
||||||
|
]);
|
||||||
|
|
||||||
|
expect($user->name)->toBe('Test User')
|
||||||
|
->and($user->email)->toBe('test@example.com')
|
||||||
|
->and($user->exists)->toBeTrue();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has guarded attributes', function () {
|
||||||
|
$guarded = ['id'];
|
||||||
|
|
||||||
|
expect(User::make()->getGuarded())->toEqual($guarded);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has hidden attributes', function () {
|
||||||
|
$hidden = ['password', 'remember_token'];
|
||||||
|
|
||||||
|
expect(User::make()->getHidden())->toEqual($hidden);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('has email verification timestamp', function () {
|
||||||
|
$user = User::factory()->create();
|
||||||
|
|
||||||
|
expect($user->getCasts())->toHaveKey('email_verified_at');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('can verify email', function () {
|
||||||
|
$user = User::factory()->create(['email_verified_at' => null]);
|
||||||
|
|
||||||
|
expect($user->email_verified_at)->toBeNull();
|
||||||
|
|
||||||
|
$user->markEmailAsVerified();
|
||||||
|
|
||||||
|
expect($user->email_verified_at)->not()->toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
46
tests/Unit/Traits/WithCommentTest.php
Normal file
46
tests/Unit/Traits/WithCommentTest.php
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Traits\Enum\WithComment;
|
||||||
|
use Filament\Support\Contracts\HasLabel;
|
||||||
|
|
||||||
|
enum TestCommentEnum: string implements HasLabel
|
||||||
|
{
|
||||||
|
use WithComment;
|
||||||
|
|
||||||
|
case ACTIVE = 'active';
|
||||||
|
case INACTIVE = 'inactive';
|
||||||
|
|
||||||
|
public function getLabel(): ?string
|
||||||
|
{
|
||||||
|
return match ($this) {
|
||||||
|
self::ACTIVE => 'Status Aktif',
|
||||||
|
self::INACTIVE => 'Status Tidak Aktif',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('WithComment Trait', function () {
|
||||||
|
it('can generate comment string from enum cases', function () {
|
||||||
|
$comment = TestCommentEnum::comment();
|
||||||
|
|
||||||
|
expect($comment)->toBeString()
|
||||||
|
->and($comment)->toContain('active: Status Aktif')
|
||||||
|
->and($comment)->toContain('inactive: Status Tidak Aktif');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('formats comment with comma separation', function () {
|
||||||
|
$comment = TestCommentEnum::comment();
|
||||||
|
|
||||||
|
expect($comment)->toContain(', ');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('includes all enum cases in comment', function () {
|
||||||
|
$comment = TestCommentEnum::comment();
|
||||||
|
$cases = TestCommentEnum::cases();
|
||||||
|
|
||||||
|
foreach ($cases as $case) {
|
||||||
|
expect($comment)->toContain($case->value);
|
||||||
|
expect($comment)->toContain($case->getLabel());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
29
tests/Unit/Traits/WithValueTest.php
Normal file
29
tests/Unit/Traits/WithValueTest.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Traits\Enum\WithValue;
|
||||||
|
|
||||||
|
enum TestValueEnum: string
|
||||||
|
{
|
||||||
|
use WithValue;
|
||||||
|
|
||||||
|
case ACTIVE = 'active';
|
||||||
|
case INACTIVE = 'inactive';
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('WithValue Trait', function () {
|
||||||
|
it('can get all values from enum cases', function () {
|
||||||
|
$values = TestValueEnum::values();
|
||||||
|
|
||||||
|
expect($values)->toBeArray()
|
||||||
|
->and($values)->toEqual(['active', 'inactive'])
|
||||||
|
->and($values)->toHaveCount(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns correct value types', function () {
|
||||||
|
$values = TestValueEnum::values();
|
||||||
|
|
||||||
|
foreach ($values as $value) {
|
||||||
|
expect($value)->toBeString();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue
Block a user