diff --git a/.forgejo/workflows/ci.yml b/.forgejo/workflows/ci.yml index 3d6d45e..8b4c936 100644 --- a/.forgejo/workflows/ci.yml +++ b/.forgejo/workflows/ci.yml @@ -18,7 +18,6 @@ jobs: uses: https://github.com/shivammathur/setup-php@v2 with: php-version: '8.3' - phpts: zts extensions: pdo_sqlite, mbstring, xml, dom coverage: pcov @@ -35,13 +34,8 @@ jobs: - name: Prepare environment run: cp .env.testing .env - - name: Debug Pint - run: | - php -v - vendor/bin/pint --version - vendor/bin/pint - git diff --stat - git diff | head -200 + - name: Lint + run: vendor/bin/pint --test - name: Static analysis run: vendor/bin/phpstan analyse diff --git a/app/Http/Controllers/Auth/NewPasswordController.php b/app/Http/Controllers/Auth/NewPasswordController.php index e8368bd..fc16e14 100644 --- a/app/Http/Controllers/Auth/NewPasswordController.php +++ b/app/Http/Controllers/Auth/NewPasswordController.php @@ -11,6 +11,7 @@ use Illuminate\Support\Facades\Password; use Illuminate\Support\Str; use Illuminate\Validation\Rules; +use Illuminate\Validation\ValidationException; use Illuminate\View\View; class NewPasswordController extends Controller @@ -26,7 +27,7 @@ public function create(Request $request): View /** * Handle an incoming new password request. * - * @throws \Illuminate\Validation\ValidationException + * @throws ValidationException */ public function store(Request $request): RedirectResponse { diff --git a/app/Http/Controllers/Auth/PasswordResetLinkController.php b/app/Http/Controllers/Auth/PasswordResetLinkController.php index bf1ebfa..1bc9c11 100644 --- a/app/Http/Controllers/Auth/PasswordResetLinkController.php +++ b/app/Http/Controllers/Auth/PasswordResetLinkController.php @@ -6,6 +6,7 @@ use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; use Illuminate\Support\Facades\Password; +use Illuminate\Validation\ValidationException; use Illuminate\View\View; class PasswordResetLinkController extends Controller @@ -21,7 +22,7 @@ public function create(): View /** * Handle an incoming password reset link request. * - * @throws \Illuminate\Validation\ValidationException + * @throws ValidationException */ public function store(Request $request): RedirectResponse { diff --git a/app/Http/Controllers/Auth/RegisteredUserController.php b/app/Http/Controllers/Auth/RegisteredUserController.php index 0739e2e..44a3930 100644 --- a/app/Http/Controllers/Auth/RegisteredUserController.php +++ b/app/Http/Controllers/Auth/RegisteredUserController.php @@ -10,6 +10,7 @@ use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Hash; use Illuminate\Validation\Rules; +use Illuminate\Validation\ValidationException; use Illuminate\View\View; class RegisteredUserController extends Controller @@ -25,7 +26,7 @@ public function create(): View /** * Handle an incoming registration request. * - * @throws \Illuminate\Validation\ValidationException + * @throws ValidationException */ public function store(Request $request): RedirectResponse { diff --git a/app/Http/Middleware/HandleAppearance.php b/app/Http/Middleware/HandleAppearance.php index f1a02bb..1a01684 100644 --- a/app/Http/Middleware/HandleAppearance.php +++ b/app/Http/Middleware/HandleAppearance.php @@ -12,7 +12,7 @@ class HandleAppearance /** * Handle an incoming request. * - * @param \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response) $next + * @param Closure(Request): (Response) $next */ public function handle(Request $request, Closure $next): Response { diff --git a/app/Http/Requests/Auth/LoginRequest.php b/app/Http/Requests/Auth/LoginRequest.php index 2574642..711e0a1 100644 --- a/app/Http/Requests/Auth/LoginRequest.php +++ b/app/Http/Requests/Auth/LoginRequest.php @@ -3,6 +3,7 @@ namespace App\Http\Requests\Auth; use Illuminate\Auth\Events\Lockout; +use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\RateLimiter; @@ -22,7 +23,7 @@ public function authorize(): bool /** * Get the validation rules that apply to the request. * - * @return array|string> + * @return array|string> */ public function rules(): array { @@ -35,7 +36,7 @@ public function rules(): array /** * Attempt to authenticate the request's credentials. * - * @throws \Illuminate\Validation\ValidationException + * @throws ValidationException */ public function authenticate(): void { @@ -55,7 +56,7 @@ public function authenticate(): void /** * Ensure the login request is not rate limited. * - * @throws \Illuminate\Validation\ValidationException + * @throws ValidationException */ public function ensureIsNotRateLimited(): void { diff --git a/app/Http/Requests/ProfileUpdateRequest.php b/app/Http/Requests/ProfileUpdateRequest.php index 3622a8f..e2202dd 100644 --- a/app/Http/Requests/ProfileUpdateRequest.php +++ b/app/Http/Requests/ProfileUpdateRequest.php @@ -3,6 +3,7 @@ namespace App\Http\Requests; use App\Models\User; +use Illuminate\Contracts\Validation\ValidationRule; use Illuminate\Foundation\Http\FormRequest; use Illuminate\Validation\Rule; @@ -11,7 +12,7 @@ class ProfileUpdateRequest extends FormRequest /** * Get the validation rules that apply to the request. * - * @return array|string> + * @return array|string> */ public function rules(): array { diff --git a/app/Http/Resources/ArticlePublicationResource.php b/app/Http/Resources/ArticlePublicationResource.php index 9640f57..2e28574 100644 --- a/app/Http/Resources/ArticlePublicationResource.php +++ b/app/Http/Resources/ArticlePublicationResource.php @@ -2,11 +2,12 @@ namespace App\Http\Resources; +use App\Models\ArticlePublication; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; /** - * @mixin \App\Models\ArticlePublication + * @mixin ArticlePublication */ class ArticlePublicationResource extends JsonResource { diff --git a/app/Http/Resources/ArticleResource.php b/app/Http/Resources/ArticleResource.php index 79da658..79760b5 100644 --- a/app/Http/Resources/ArticleResource.php +++ b/app/Http/Resources/ArticleResource.php @@ -2,11 +2,12 @@ namespace App\Http\Resources; +use App\Models\Article; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; /** - * @mixin \App\Models\Article + * @mixin Article */ class ArticleResource extends JsonResource { diff --git a/app/Http/Resources/FeedResource.php b/app/Http/Resources/FeedResource.php index 1c50a90..b2cc7d2 100644 --- a/app/Http/Resources/FeedResource.php +++ b/app/Http/Resources/FeedResource.php @@ -2,11 +2,12 @@ namespace App\Http\Resources; +use App\Models\Feed; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; /** - * @mixin \App\Models\Feed + * @mixin Feed */ class FeedResource extends JsonResource { diff --git a/app/Http/Resources/PlatformAccountResource.php b/app/Http/Resources/PlatformAccountResource.php index 6aa9c04..46d7cc6 100644 --- a/app/Http/Resources/PlatformAccountResource.php +++ b/app/Http/Resources/PlatformAccountResource.php @@ -2,14 +2,15 @@ namespace App\Http\Resources; +use App\Models\PlatformAccount; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; /** - * @mixin \App\Models\PlatformAccount + * @mixin PlatformAccount */ /** - * @mixin \App\Models\PlatformAccount + * @mixin PlatformAccount */ class PlatformAccountResource extends JsonResource { diff --git a/app/Http/Resources/PlatformChannelResource.php b/app/Http/Resources/PlatformChannelResource.php index c0d3338..f3b7f27 100644 --- a/app/Http/Resources/PlatformChannelResource.php +++ b/app/Http/Resources/PlatformChannelResource.php @@ -2,11 +2,12 @@ namespace App\Http\Resources; +use App\Models\PlatformChannel; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; /** - * @mixin \App\Models\PlatformChannel + * @mixin PlatformChannel */ class PlatformChannelResource extends JsonResource { diff --git a/app/Http/Resources/PlatformInstanceResource.php b/app/Http/Resources/PlatformInstanceResource.php index c95f1f4..45ffa16 100644 --- a/app/Http/Resources/PlatformInstanceResource.php +++ b/app/Http/Resources/PlatformInstanceResource.php @@ -2,11 +2,12 @@ namespace App\Http\Resources; +use App\Models\PlatformInstance; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; /** - * @mixin \App\Models\PlatformInstance + * @mixin PlatformInstance */ class PlatformInstanceResource extends JsonResource { diff --git a/app/Http/Resources/RouteArticleResource.php b/app/Http/Resources/RouteArticleResource.php index 73d9520..c56869b 100644 --- a/app/Http/Resources/RouteArticleResource.php +++ b/app/Http/Resources/RouteArticleResource.php @@ -2,11 +2,12 @@ namespace App\Http\Resources; +use App\Models\RouteArticle; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; /** - * @mixin \App\Models\RouteArticle + * @mixin RouteArticle */ class RouteArticleResource extends JsonResource { diff --git a/app/Http/Resources/RouteResource.php b/app/Http/Resources/RouteResource.php index f294f1a..e8d89cb 100644 --- a/app/Http/Resources/RouteResource.php +++ b/app/Http/Resources/RouteResource.php @@ -2,11 +2,12 @@ namespace App\Http\Resources; +use App\Models\Route; use Illuminate\Http\Request; use Illuminate\Http\Resources\Json\JsonResource; /** - * @mixin \App\Models\Route + * @mixin Route */ class RouteResource extends JsonResource { diff --git a/app/Livewire/Articles.php b/app/Livewire/Articles.php index 8c5d11f..2d26538 100644 --- a/app/Livewire/Articles.php +++ b/app/Livewire/Articles.php @@ -5,6 +5,7 @@ use App\Enums\ApprovalStatusEnum; use App\Jobs\ArticleDiscoveryJob; use App\Models\RouteArticle; +use Illuminate\Contracts\View\View; use Livewire\Component; use Livewire\WithPagination; @@ -61,7 +62,7 @@ public function refresh(): void $this->dispatch('refresh-started'); } - public function render(): \Illuminate\Contracts\View\View + public function render(): View { $query = RouteArticle::with(['article.feed', 'feed', 'platformChannel']) ->orderBy('created_at', 'desc'); diff --git a/app/Livewire/Channels.php b/app/Livewire/Channels.php index a4aff29..49ea79c 100644 --- a/app/Livewire/Channels.php +++ b/app/Livewire/Channels.php @@ -4,6 +4,7 @@ use App\Models\PlatformAccount; use App\Models\PlatformChannel; +use Illuminate\Contracts\View\View; use Livewire\Component; class Channels extends Component @@ -51,7 +52,7 @@ public function detachAccount(int $channelId, int $accountId): void $channel->platformAccounts()->detach($accountId); } - public function render(): \Illuminate\Contracts\View\View + public function render(): View { $channels = PlatformChannel::with(['platformInstance', 'platformAccounts'])->orderBy('name')->get(); $allAccounts = PlatformAccount::where('is_active', true)->get(); diff --git a/app/Livewire/Dashboard.php b/app/Livewire/Dashboard.php index 0ffb4e9..c65b6f8 100644 --- a/app/Livewire/Dashboard.php +++ b/app/Livewire/Dashboard.php @@ -3,6 +3,7 @@ namespace App\Livewire; use App\Services\DashboardStatsService; +use Illuminate\Contracts\View\View; use Livewire\Component; class Dashboard extends Component @@ -19,7 +20,7 @@ public function setPeriod(string $period): void $this->period = $period; } - public function render(): \Illuminate\Contracts\View\View + public function render(): View { $service = app(DashboardStatsService::class); diff --git a/app/Livewire/Feeds.php b/app/Livewire/Feeds.php index 89f8b42..b1f86be 100644 --- a/app/Livewire/Feeds.php +++ b/app/Livewire/Feeds.php @@ -3,6 +3,7 @@ namespace App\Livewire; use App\Models\Feed; +use Illuminate\Contracts\View\View; use Livewire\Component; class Feeds extends Component @@ -14,7 +15,7 @@ public function toggle(int $feedId): void $feed->save(); } - public function render(): \Illuminate\Contracts\View\View + public function render(): View { $feeds = Feed::orderBy('name')->get(); diff --git a/app/Livewire/Onboarding.php b/app/Livewire/Onboarding.php index 9c17fcf..919514e 100644 --- a/app/Livewire/Onboarding.php +++ b/app/Livewire/Onboarding.php @@ -18,7 +18,9 @@ use App\Models\Setting; use App\Services\OnboardingService; use Exception; +use Illuminate\Contracts\View\View; use InvalidArgumentException; +use Livewire\Attributes\Locked; use Livewire\Component; use RuntimeException; @@ -68,7 +70,7 @@ class Onboarding extends Component public bool $isLoading = false; - #[\Livewire\Attributes\Locked] + #[Locked] public ?int $previousChannelLanguageId = null; protected CreatePlatformAccountAction $createPlatformAccountAction; @@ -406,7 +408,7 @@ public function getChannelLanguage(): ?Language return Language::find($this->channelLanguageId); } - public function render(): \Illuminate\Contracts\View\View + public function render(): View { // For channel step: only show languages that have providers $availableCodes = $this->getAvailableLanguageCodes(); diff --git a/app/Livewire/Routes.php b/app/Livewire/Routes.php index 1578e43..64ee812 100644 --- a/app/Livewire/Routes.php +++ b/app/Livewire/Routes.php @@ -6,6 +6,7 @@ use App\Models\Keyword; use App\Models\PlatformChannel; use App\Models\Route; +use Illuminate\Contracts\View\View; use Livewire\Component; class Routes extends Component @@ -171,7 +172,7 @@ public function deleteKeyword(int $keywordId): void Keyword::destroy($keywordId); } - public function render(): \Illuminate\Contracts\View\View + public function render(): View { $routes = Route::with(['feed', 'platformChannel.platformInstance']) ->orderBy('priority', 'desc') diff --git a/app/Livewire/Settings.php b/app/Livewire/Settings.php index 9c97752..693db05 100644 --- a/app/Livewire/Settings.php +++ b/app/Livewire/Settings.php @@ -3,6 +3,7 @@ namespace App\Livewire; use App\Models\Setting; +use Illuminate\Contracts\View\View; use Livewire\Component; class Settings extends Component @@ -76,7 +77,7 @@ public function clearMessages(): void $this->errorMessage = null; } - public function render(): \Illuminate\Contracts\View\View + public function render(): View { return view('livewire.settings')->layout('layouts.app'); } diff --git a/app/Models/ArticlePublication.php b/app/Models/ArticlePublication.php index ee29b72..163f2e8 100644 --- a/app/Models/ArticlePublication.php +++ b/app/Models/ArticlePublication.php @@ -6,6 +6,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Relations\BelongsTo; +use Illuminate\Support\Carbon; /** * @property int $id @@ -15,9 +16,9 @@ * @property string $platform * @property string $published_by * @property array|null $publication_data - * @property \Illuminate\Support\Carbon $published_at - * @property \Illuminate\Support\Carbon $created_at - * @property \Illuminate\Support\Carbon $updated_at + * @property Carbon $published_at + * @property Carbon $created_at + * @property Carbon $updated_at * * @method static create(array $array) */ diff --git a/app/Models/PlatformChannelPost.php b/app/Models/PlatformChannelPost.php index b2a8652..a411b24 100644 --- a/app/Models/PlatformChannelPost.php +++ b/app/Models/PlatformChannelPost.php @@ -3,6 +3,7 @@ namespace App\Models; use App\Enums\PlatformEnum; +use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; @@ -12,7 +13,7 @@ */ class PlatformChannelPost extends Model { - /** @use HasFactory<\Illuminate\Database\Eloquent\Factories\Factory> */ + /** @use HasFactory> */ use HasFactory; protected $fillable = [ diff --git a/app/Models/User.php b/app/Models/User.php index 91135d7..c016ca6 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -3,6 +3,7 @@ namespace App\Models; // use Illuminate\Contracts\Auth\MustVerifyEmail; +use Database\Factories\UserFactory; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; @@ -10,7 +11,7 @@ class User extends Authenticatable { - /** @use HasFactory<\Database\Factories\UserFactory> */ + /** @use HasFactory */ use HasApiTokens, HasFactory, Notifiable; /** diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index c9b6f5d..573fa39 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -5,8 +5,12 @@ use App\Enums\LogLevelEnum; use App\Events\ActionPerformed; use App\Events\ExceptionOccurred; +use App\Events\NewArticleFetched; +use App\Events\RouteArticleApproved; use App\Listeners\LogActionListener; use App\Listeners\LogExceptionToDatabase; +use App\Listeners\PublishApprovedArticleListener; +use App\Listeners\ValidateArticleListener; use Error; use Illuminate\Contracts\Debug\ExceptionHandler; use Illuminate\Support\Facades\Event; @@ -31,13 +35,13 @@ public function boot(): void ); Event::listen( - \App\Events\NewArticleFetched::class, - \App\Listeners\ValidateArticleListener::class, + NewArticleFetched::class, + ValidateArticleListener::class, ); Event::listen( - \App\Events\RouteArticleApproved::class, - \App\Listeners\PublishApprovedArticleListener::class, + RouteArticleApproved::class, + PublishApprovedArticleListener::class, ); app()->make(ExceptionHandler::class) diff --git a/app/Services/Article/ArticleFetcher.php b/app/Services/Article/ArticleFetcher.php index 46435a8..e655e8d 100644 --- a/app/Services/Article/ArticleFetcher.php +++ b/app/Services/Article/ArticleFetcher.php @@ -155,7 +155,7 @@ private function saveArticle(string $url, ?int $feedId = null): Article } return $article; - } catch (\Exception $e) { + } catch (Exception $e) { $this->logSaver->error('Failed to create article', null, [ 'url' => $url, 'feed_id' => $feedId, diff --git a/app/Services/Http/HttpFetcher.php b/app/Services/Http/HttpFetcher.php index 1caa6a6..670b0de 100644 --- a/app/Services/Http/HttpFetcher.php +++ b/app/Services/Http/HttpFetcher.php @@ -3,6 +3,7 @@ namespace App\Services\Http; use Exception; +use Illuminate\Http\Client\Response; use Illuminate\Support\Facades\Http; class HttpFetcher @@ -48,7 +49,7 @@ public static function fetchMultipleUrls(array $urls): array ->reject(fn ($response, $index) => $response instanceof Exception) ->map(function ($response, $index) use ($urls) { $url = $urls[$index]; - /** @var \Illuminate\Http\Client\Response $response */ + /** @var Response $response */ try { if ($response->successful()) { return [ diff --git a/bootstrap/app.php b/bootstrap/app.php index 5db8c44..0ba51af 100644 --- a/bootstrap/app.php +++ b/bootstrap/app.php @@ -1,5 +1,7 @@ withExceptions(function (Exceptions $exceptions) { $exceptions->reportable(function (Throwable $e) { $level = match (true) { - $e instanceof Error => \App\Enums\LogLevelEnum::CRITICAL, - $e instanceof RuntimeException => \App\Enums\LogLevelEnum::ERROR, - $e instanceof InvalidArgumentException => \App\Enums\LogLevelEnum::WARNING, - default => \App\Enums\LogLevelEnum::ERROR, + $e instanceof Error => LogLevelEnum::CRITICAL, + $e instanceof RuntimeException => LogLevelEnum::ERROR, + $e instanceof InvalidArgumentException => LogLevelEnum::WARNING, + default => LogLevelEnum::ERROR, }; - App\Events\ExceptionOccurred::dispatch( + ExceptionOccurred::dispatch( $e, $level, $e->getMessage(), diff --git a/bootstrap/providers.php b/bootstrap/providers.php index 4e3b440..2345aa6 100644 --- a/bootstrap/providers.php +++ b/bootstrap/providers.php @@ -1,6 +1,9 @@ [ 'users' => [ 'driver' => 'eloquent', - 'model' => env('AUTH_MODEL', App\Models\User::class), + 'model' => env('AUTH_MODEL', User::class), ], // 'users' => [ diff --git a/config/feed.php b/config/feed.php index 73227fe..4215761 100644 --- a/config/feed.php +++ b/config/feed.php @@ -1,5 +1,13 @@ ['url' => 'https://www.vrt.be/vrtnws/nl/'], ], 'parsers' => [ - 'homepage' => \App\Services\Parsers\VrtHomepageParserAdapter::class, - 'article' => \App\Services\Parsers\VrtArticleParser::class, - 'article_page' => \App\Services\Parsers\VrtArticlePageParser::class, + 'homepage' => VrtHomepageParserAdapter::class, + 'article' => VrtArticleParser::class, + 'article_page' => VrtArticlePageParser::class, ], ], 'belga' => [ @@ -39,8 +47,8 @@ 'en' => ['url' => 'https://www.belganewsagency.eu/feed'], ], 'parsers' => [ - 'article' => \App\Services\Parsers\BelgaArticleParser::class, - 'article_page' => \App\Services\Parsers\BelgaArticlePageParser::class, + 'article' => BelgaArticleParser::class, + 'article_page' => BelgaArticlePageParser::class, ], ], 'guardian' => [ @@ -53,8 +61,8 @@ 'en' => ['url' => 'https://www.theguardian.com/international/rss'], ], 'parsers' => [ - 'article' => \App\Services\Parsers\GuardianArticleParser::class, - 'article_page' => \App\Services\Parsers\GuardianArticlePageParser::class, + 'article' => GuardianArticleParser::class, + 'article_page' => GuardianArticlePageParser::class, ], ], ], diff --git a/config/sanctum.php b/config/sanctum.php index 44527d6..cde73cf 100644 --- a/config/sanctum.php +++ b/config/sanctum.php @@ -1,5 +1,8 @@ [ - 'authenticate_session' => Laravel\Sanctum\Http\Middleware\AuthenticateSession::class, - 'encrypt_cookies' => Illuminate\Cookie\Middleware\EncryptCookies::class, - 'validate_csrf_token' => Illuminate\Foundation\Http\Middleware\ValidateCsrfToken::class, + 'authenticate_session' => AuthenticateSession::class, + 'encrypt_cookies' => EncryptCookies::class, + 'validate_csrf_token' => ValidateCsrfToken::class, ], ]; diff --git a/database/factories/ArticleFactory.php b/database/factories/ArticleFactory.php index d5a57bb..3e15408 100644 --- a/database/factories/ArticleFactory.php +++ b/database/factories/ArticleFactory.php @@ -2,10 +2,12 @@ namespace Database\Factories; +use App\Models\Article; +use App\Models\Feed; use Illuminate\Database\Eloquent\Factories\Factory; /** - * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Article> + * @extends Factory
*/ class ArticleFactory extends Factory { @@ -17,7 +19,7 @@ class ArticleFactory extends Factory public function definition(): array { return [ - 'feed_id' => \App\Models\Feed::factory(), + 'feed_id' => Feed::factory(), 'url' => $this->faker->url(), 'title' => $this->faker->sentence(), 'description' => $this->faker->paragraph(), diff --git a/database/factories/KeywordFactory.php b/database/factories/KeywordFactory.php index db36fd1..c807a17 100644 --- a/database/factories/KeywordFactory.php +++ b/database/factories/KeywordFactory.php @@ -2,7 +2,9 @@ namespace Database\Factories; +use App\Models\Feed; use App\Models\Keyword; +use App\Models\PlatformChannel; use Illuminate\Database\Eloquent\Factories\Factory; class KeywordFactory extends Factory @@ -12,8 +14,8 @@ class KeywordFactory extends Factory public function definition(): array { return [ - 'feed_id' => \App\Models\Feed::factory(), - 'platform_channel_id' => \App\Models\PlatformChannel::factory(), + 'feed_id' => Feed::factory(), + 'platform_channel_id' => PlatformChannel::factory(), 'keyword' => $this->faker->word(), 'is_active' => $this->faker->boolean(70), // 70% chance of being active 'created_at' => $this->faker->dateTimeBetween('-1 year', 'now'), @@ -21,14 +23,14 @@ public function definition(): array ]; } - public function forFeed(\App\Models\Feed $feed): static + public function forFeed(Feed $feed): static { return $this->state(fn (array $attributes) => [ 'feed_id' => $feed->id, ]); } - public function forChannel(\App\Models\PlatformChannel $channel): static + public function forChannel(PlatformChannel $channel): static { return $this->state(fn (array $attributes) => [ 'platform_channel_id' => $channel->id, diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index 584104c..c4ceb07 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -2,12 +2,13 @@ namespace Database\Factories; +use App\Models\User; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Facades\Hash; use Illuminate\Support\Str; /** - * @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\User> + * @extends Factory */ class UserFactory extends Factory { diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index fb3f0fd..15c4715 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -54,6 +54,30 @@ parameters: count: 1 path: tests/Unit/Enums/PlatformEnumTest.php + - + message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$feed\.$#' + identifier: property.notFound + count: 4 + path: tests/Unit/Jobs/CleanupArticlesJobTest.php + + - + message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$feed_id\.$#' + identifier: property.notFound + count: 4 + path: tests/Unit/Jobs/CleanupArticlesJobTest.php + + - + message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$id\.$#' + identifier: property.notFound + count: 1 + path: tests/Unit/Jobs/CleanupArticlesJobTest.php + + - + message: '#^Access to an undefined property Illuminate\\Database\\Eloquent\\Model\:\:\$platform_channel_id\.$#' + identifier: property.notFound + count: 4 + path: tests/Unit/Jobs/CleanupArticlesJobTest.php + - message: '#^Access to an undefined property App\\Models\\PlatformChannel\:\:\$pivot\.$#' identifier: property.notFound diff --git a/tests/Feature/DatabaseIntegrationTest.php b/tests/Feature/DatabaseIntegrationTest.php index 982ec93..2eebb44 100644 --- a/tests/Feature/DatabaseIntegrationTest.php +++ b/tests/Feature/DatabaseIntegrationTest.php @@ -16,6 +16,8 @@ use App\Models\Route; use App\Models\Setting; use App\Models\User; +use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\QueryException; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; @@ -332,7 +334,7 @@ public function test_model_soft_deletes_work_correctly(): void public function test_database_constraints_are_enforced(): void { // Test foreign key constraints - $this->expectException(\Illuminate\Database\QueryException::class); + $this->expectException(QueryException::class); // Try to create article with non-existent feed_id Article::factory()->create(['feed_id' => 99999]); @@ -355,7 +357,7 @@ public function test_all_factories_work_correctly(): void foreach ($models as $model) { $this->assertNotNull($model); - $this->assertInstanceOf(\Illuminate\Database\Eloquent\Model::class, $model); + $this->assertInstanceOf(Model::class, $model); } } } diff --git a/tests/Feature/Jobs/CheckFeedStalenessJobTest.php b/tests/Feature/Jobs/CheckFeedStalenessJobTest.php index 4e5c0f2..9788fd9 100644 --- a/tests/Feature/Jobs/CheckFeedStalenessJobTest.php +++ b/tests/Feature/Jobs/CheckFeedStalenessJobTest.php @@ -8,6 +8,7 @@ use App\Models\Feed; use App\Models\Notification; use App\Models\Setting; +use App\Services\Notification\NotificationService; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; @@ -128,6 +129,6 @@ public function test_never_fetched_feed_creates_notification(): void private function dispatch(): void { - (new CheckFeedStalenessJob)->handle(app(\App\Services\Notification\NotificationService::class)); + (new CheckFeedStalenessJob)->handle(app(NotificationService::class)); } } diff --git a/tests/Feature/JobsAndEventsTest.php b/tests/Feature/JobsAndEventsTest.php index e1337ac..b5c793e 100644 --- a/tests/Feature/JobsAndEventsTest.php +++ b/tests/Feature/JobsAndEventsTest.php @@ -2,10 +2,13 @@ namespace Tests\Feature; +use App\Enums\ApprovalStatusEnum; +use App\Enums\LogLevelEnum; use App\Events\ActionPerformed; use App\Events\ExceptionLogged; use App\Events\ExceptionOccurred; use App\Events\NewArticleFetched; +use App\Events\RouteArticleApproved; use App\Jobs\ArticleDiscoveryForFeedJob; use App\Jobs\ArticleDiscoveryJob; use App\Jobs\PublishNextArticleJob; @@ -14,8 +17,11 @@ use App\Listeners\ValidateArticleListener; use App\Models\Article; use App\Models\Feed; +use App\Models\Keyword; use App\Models\Log; use App\Models\PlatformChannel; +use App\Models\Route; +use App\Models\RouteArticle; use App\Models\Setting; use App\Services\Article\ArticleFetcher; use App\Services\Log\LogSaver; @@ -57,14 +63,14 @@ public function test_article_discovery_for_feed_job_processes_feed(): void ]); // Mock the ArticleFetcher service in the container - $mockFetcher = \Mockery::mock(\App\Services\Article\ArticleFetcher::class); + $mockFetcher = \Mockery::mock(ArticleFetcher::class); $article1 = Article::factory()->create(['url' => 'https://example.com/article1', 'feed_id' => $feed->id]); $article2 = Article::factory()->create(['url' => 'https://example.com/article2', 'feed_id' => $feed->id]); $mockFetcher->shouldReceive('getArticlesFromFeed') ->with($feed) ->andReturn(collect([$article1, $article2])); - $this->app->instance(\App\Services\Article\ArticleFetcher::class, $mockFetcher); + $this->app->instance(ArticleFetcher::class, $mockFetcher); $logSaver = app(LogSaver::class); $articleFetcher = app(ArticleFetcher::class); @@ -118,7 +124,7 @@ public function test_exception_occurred_event_is_dispatched(): void $exception = new \Exception('Test exception'); - event(new ExceptionOccurred($exception, \App\Enums\LogLevelEnum::ERROR, 'Test exception', ['context' => 'test'])); + event(new ExceptionOccurred($exception, LogLevelEnum::ERROR, 'Test exception', ['context' => 'test'])); Event::assertDispatched(ExceptionOccurred::class, function (ExceptionOccurred $event) { return $event->exception->getMessage() === 'Test exception'; @@ -148,9 +154,9 @@ public function test_validate_article_listener_processes_new_article(): void Setting::setBool('enable_publishing_approvals', false); $feed = Feed::factory()->create(); - /** @var \App\Models\Route $route */ - $route = \App\Models\Route::factory()->active()->create(['feed_id' => $feed->id]); - \App\Models\Keyword::factory()->active()->create([ + /** @var Route $route */ + $route = Route::factory()->active()->create(['feed_id' => $feed->id]); + Keyword::factory()->active()->create([ 'feed_id' => $feed->id, 'platform_channel_id' => $route->platform_channel_id, 'keyword' => 'Belgium', @@ -161,8 +167,8 @@ public function test_validate_article_listener_processes_new_article(): void ]); // Mock ArticleFetcher to return valid article data - $mockFetcher = \Mockery::mock(\App\Services\Article\ArticleFetcher::class); - $this->app->instance(\App\Services\Article\ArticleFetcher::class, $mockFetcher); + $mockFetcher = \Mockery::mock(ArticleFetcher::class); + $this->app->instance(ArticleFetcher::class, $mockFetcher); $mockFetcher->shouldReceive('fetchArticleData') ->with($article) ->andReturn([ @@ -179,9 +185,9 @@ public function test_validate_article_listener_processes_new_article(): void $article->refresh(); $this->assertNotNull($article->validated_at); - $routeArticle = \App\Models\RouteArticle::where('article_id', $article->id)->first(); + $routeArticle = RouteArticle::where('article_id', $article->id)->first(); $this->assertNotNull($routeArticle); - $this->assertEquals(\App\Enums\ApprovalStatusEnum::APPROVED, $routeArticle->approval_status); + $this->assertEquals(ApprovalStatusEnum::APPROVED, $routeArticle->approval_status); } public function test_log_exception_to_database_listener_creates_log(): void @@ -194,7 +200,7 @@ public function test_log_exception_to_database_listener_creates_log(): void $listener = new LogExceptionToDatabase; $exception = new \Exception('Test exception message'); - $event = new ExceptionOccurred($exception, \App\Enums\LogLevelEnum::ERROR, 'Test exception message'); + $event = new ExceptionOccurred($exception, LogLevelEnum::ERROR, 'Test exception message'); $listener->handle($event); @@ -205,7 +211,7 @@ public function test_log_exception_to_database_listener_creates_log(): void $savedLog = Log::where('message', 'Test exception message')->first(); $this->assertNotNull($savedLog); - $this->assertEquals(\App\Enums\LogLevelEnum::ERROR, $savedLog->level); + $this->assertEquals(LogLevelEnum::ERROR, $savedLog->level); } public function test_event_listener_registration_works(): void @@ -217,7 +223,7 @@ public function test_event_listener_registration_works(): void $listeners = Event::getListeners(NewArticleFetched::class); $this->assertNotEmpty($listeners); - $listeners = Event::getListeners(\App\Events\RouteArticleApproved::class); + $listeners = Event::getListeners(RouteArticleApproved::class); $this->assertNotEmpty($listeners); $listeners = Event::getListeners(ExceptionOccurred::class); diff --git a/tests/Feature/ValidateArticleListenerTest.php b/tests/Feature/ValidateArticleListenerTest.php index 57529a6..5743555 100644 --- a/tests/Feature/ValidateArticleListenerTest.php +++ b/tests/Feature/ValidateArticleListenerTest.php @@ -12,6 +12,7 @@ use App\Models\Route; use App\Models\RouteArticle; use App\Services\Article\ArticleFetcher; +use App\Services\Article\ValidationService; use Illuminate\Foundation\Testing\RefreshDatabase; use Mockery; use Tests\TestCase; @@ -32,7 +33,7 @@ private function createListenerWithMockedFetcher(?string $content = 'Some articl ); return new ValidateArticleListener( - new \App\Services\Article\ValidationService($articleFetcher) + new ValidationService($articleFetcher) ); } @@ -113,7 +114,7 @@ public function test_listener_handles_validation_errors_gracefully(): void $articleFetcher->shouldReceive('fetchArticleData')->andThrow(new \Exception('Fetch failed')); $listener = new ValidateArticleListener( - new \App\Services\Article\ValidationService($articleFetcher) + new ValidationService($articleFetcher) ); $feed = Feed::factory()->create(); diff --git a/tests/Traits/CreatesArticleFetcher.php b/tests/Traits/CreatesArticleFetcher.php index ad2f985..adeda40 100644 --- a/tests/Traits/CreatesArticleFetcher.php +++ b/tests/Traits/CreatesArticleFetcher.php @@ -5,6 +5,7 @@ use App\Services\Article\ArticleFetcher; use App\Services\Log\LogSaver; use Mockery; +use Mockery\MockInterface; trait CreatesArticleFetcher { @@ -21,7 +22,7 @@ protected function createArticleFetcher(?LogSaver $logSaver = null): ArticleFetc return new ArticleFetcher($logSaver); } - /** @return array{ArticleFetcher, \Mockery\MockInterface} */ + /** @return array{ArticleFetcher, MockInterface} */ protected function createArticleFetcherWithMockedLogSaver(): array { $logSaver = Mockery::mock(LogSaver::class); diff --git a/tests/Unit/Actions/CreatePlatformAccountActionTest.php b/tests/Unit/Actions/CreatePlatformAccountActionTest.php index 051c522..2c0b817 100644 --- a/tests/Unit/Actions/CreatePlatformAccountActionTest.php +++ b/tests/Unit/Actions/CreatePlatformAccountActionTest.php @@ -10,6 +10,7 @@ use App\Services\Auth\LemmyAuthService; use Illuminate\Foundation\Testing\RefreshDatabase; use Mockery; +use Mockery\MockInterface; use Tests\TestCase; class CreatePlatformAccountActionTest extends TestCase @@ -18,7 +19,7 @@ class CreatePlatformAccountActionTest extends TestCase private CreatePlatformAccountAction $action; - /** @var LemmyAuthService&\Mockery\MockInterface */ + /** @var LemmyAuthService&MockInterface */ private LemmyAuthService $lemmyAuthService; protected function setUp(): void diff --git a/tests/Unit/Events/ActionPerformedTest.php b/tests/Unit/Events/ActionPerformedTest.php index 5091bbf..7e8fb41 100644 --- a/tests/Unit/Events/ActionPerformedTest.php +++ b/tests/Unit/Events/ActionPerformedTest.php @@ -5,6 +5,7 @@ use App\Enums\LogLevelEnum; use App\Events\ActionPerformed; use Illuminate\Foundation\Events\Dispatchable; +use Illuminate\Queue\SerializesModels; use Tests\TestCase; class ActionPerformedTest extends TestCase @@ -41,7 +42,7 @@ public function test_event_uses_dispatchable_trait(): void public function test_event_does_not_use_serializes_models_trait(): void { $this->assertNotContains( - \Illuminate\Queue\SerializesModels::class, + SerializesModels::class, class_uses(ActionPerformed::class), ); } diff --git a/tests/Unit/Exceptions/RoutingMismatchExceptionTest.php b/tests/Unit/Exceptions/RoutingMismatchExceptionTest.php index b88968d..5ddd4f8 100644 --- a/tests/Unit/Exceptions/RoutingMismatchExceptionTest.php +++ b/tests/Unit/Exceptions/RoutingMismatchExceptionTest.php @@ -2,6 +2,7 @@ namespace Tests\Unit\Exceptions; +use App\Exceptions\RoutingException; use App\Exceptions\RoutingMismatchException; use App\Models\Feed; use App\Models\Language; @@ -52,7 +53,7 @@ public function test_exception_extends_routing_exception(): void $exception = new RoutingMismatchException($feed, $channel); // Assert - $this->assertInstanceOf(\App\Exceptions\RoutingException::class, $exception); + $this->assertInstanceOf(RoutingException::class, $exception); } public function test_exception_with_different_languages(): void diff --git a/tests/Unit/Jobs/ArticleDiscoveryForFeedJobTest.php b/tests/Unit/Jobs/ArticleDiscoveryForFeedJobTest.php index c1c5579..847c426 100644 --- a/tests/Unit/Jobs/ArticleDiscoveryForFeedJobTest.php +++ b/tests/Unit/Jobs/ArticleDiscoveryForFeedJobTest.php @@ -6,6 +6,8 @@ use App\Models\Feed; use App\Services\Article\ArticleFetcher; use App\Services\Log\LogSaver; +use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Foundation\Queue\Queueable; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\Queue; use Mockery; @@ -34,7 +36,7 @@ public function test_job_implements_should_queue(): void $feed = Feed::factory()->make(); $job = new ArticleDiscoveryForFeedJob($feed); - $this->assertInstanceOf(\Illuminate\Contracts\Queue\ShouldQueue::class, $job); + $this->assertInstanceOf(ShouldQueue::class, $job); } public function test_job_uses_queueable_trait(): void @@ -43,7 +45,7 @@ public function test_job_uses_queueable_trait(): void $job = new ArticleDiscoveryForFeedJob($feed); $this->assertContains( - \Illuminate\Foundation\Queue\Queueable::class, + Queueable::class, class_uses($job) ); } diff --git a/tests/Unit/Jobs/ArticleDiscoveryJobTest.php b/tests/Unit/Jobs/ArticleDiscoveryJobTest.php index d9546d0..3b27bfd 100644 --- a/tests/Unit/Jobs/ArticleDiscoveryJobTest.php +++ b/tests/Unit/Jobs/ArticleDiscoveryJobTest.php @@ -5,6 +5,7 @@ use App\Jobs\ArticleDiscoveryJob; use App\Models\Setting; use App\Services\Log\LogSaver; +use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\Queue; use Mockery; @@ -100,7 +101,7 @@ public function test_job_implements_should_queue(): void $job = new ArticleDiscoveryJob; // Assert - $this->assertInstanceOf(\Illuminate\Contracts\Queue\ShouldQueue::class, $job); + $this->assertInstanceOf(ShouldQueue::class, $job); } public function test_job_uses_queueable_trait(): void diff --git a/tests/Unit/Jobs/PublishNextArticleJobTest.php b/tests/Unit/Jobs/PublishNextArticleJobTest.php index 694789a..6614595 100644 --- a/tests/Unit/Jobs/PublishNextArticleJobTest.php +++ b/tests/Unit/Jobs/PublishNextArticleJobTest.php @@ -16,6 +16,8 @@ use App\Services\Article\ArticleFetcher; use App\Services\Notification\NotificationService; use App\Services\Publishing\ArticlePublishingService; +use Illuminate\Contracts\Queue\ShouldBeUnique; +use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Foundation\Queue\Queueable; use Illuminate\Foundation\Testing\RefreshDatabase; use Mockery; @@ -63,14 +65,14 @@ public function test_job_implements_should_queue(): void { $job = new PublishNextArticleJob; - $this->assertInstanceOf(\Illuminate\Contracts\Queue\ShouldQueue::class, $job); + $this->assertInstanceOf(ShouldQueue::class, $job); } public function test_job_implements_should_be_unique(): void { $job = new PublishNextArticleJob; - $this->assertInstanceOf(\Illuminate\Contracts\Queue\ShouldBeUnique::class, $job); + $this->assertInstanceOf(ShouldBeUnique::class, $job); } public function test_job_has_unique_for_property(): void diff --git a/tests/Unit/Jobs/SyncChannelPostsJobTest.php b/tests/Unit/Jobs/SyncChannelPostsJobTest.php index 7286a55..d439bff 100644 --- a/tests/Unit/Jobs/SyncChannelPostsJobTest.php +++ b/tests/Unit/Jobs/SyncChannelPostsJobTest.php @@ -9,6 +9,9 @@ use App\Models\PlatformInstance; use App\Services\Log\LogSaver; use Exception; +use Illuminate\Contracts\Queue\ShouldBeUnique; +use Illuminate\Contracts\Queue\ShouldQueue; +use Illuminate\Foundation\Queue\Queueable; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Queue; @@ -39,7 +42,7 @@ public function test_job_implements_should_queue(): void $channel = PlatformChannel::factory()->make(); $job = new SyncChannelPostsJob($channel); - $this->assertInstanceOf(\Illuminate\Contracts\Queue\ShouldQueue::class, $job); + $this->assertInstanceOf(ShouldQueue::class, $job); } public function test_job_implements_should_be_unique(): void @@ -47,7 +50,7 @@ public function test_job_implements_should_be_unique(): void $channel = PlatformChannel::factory()->make(); $job = new SyncChannelPostsJob($channel); - $this->assertInstanceOf(\Illuminate\Contracts\Queue\ShouldBeUnique::class, $job); + $this->assertInstanceOf(ShouldBeUnique::class, $job); } public function test_job_uses_queueable_trait(): void @@ -56,7 +59,7 @@ public function test_job_uses_queueable_trait(): void $job = new SyncChannelPostsJob($channel); $this->assertContains( - \Illuminate\Foundation\Queue\Queueable::class, + Queueable::class, class_uses($job) ); } diff --git a/tests/Unit/Models/ArticlePublicationTest.php b/tests/Unit/Models/ArticlePublicationTest.php index 3c7e69c..1949811 100644 --- a/tests/Unit/Models/ArticlePublicationTest.php +++ b/tests/Unit/Models/ArticlePublicationTest.php @@ -5,6 +5,7 @@ use App\Models\Article; use App\Models\ArticlePublication; use App\Models\PlatformChannel; +use Carbon\Carbon; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; @@ -33,7 +34,7 @@ public function test_casts_published_at_to_datetime(): void /** @var ArticlePublication $publication */ $publication = ArticlePublication::factory()->create(['published_at' => $timestamp]); - $this->assertInstanceOf(\Carbon\Carbon::class, $publication->published_at); + $this->assertInstanceOf(Carbon::class, $publication->published_at); $this->assertEquals($timestamp->format('Y-m-d H:i:s'), $publication->published_at->format('Y-m-d H:i:s')); } @@ -76,7 +77,7 @@ public function test_publication_creation_with_factory(): void $this->assertNotNull($publication->article_id); $this->assertNotNull($publication->platform_channel_id); $this->assertIsString($publication->post_id); - $this->assertInstanceOf(\Carbon\Carbon::class, $publication->published_at); + $this->assertInstanceOf(Carbon::class, $publication->published_at); $this->assertIsString($publication->published_by); } @@ -111,7 +112,7 @@ public function test_publication_factory_recently_published_state(): void /** @var ArticlePublication $publication */ $publication = ArticlePublication::factory()->recentlyPublished()->create(); - $this->assertInstanceOf(\Carbon\Carbon::class, $publication->published_at); + $this->assertInstanceOf(Carbon::class, $publication->published_at); $this->assertTrue($publication->published_at->isAfter(now()->subDay())); $this->assertTrue($publication->published_at->isBefore(now()->addMinute())); } @@ -203,7 +204,7 @@ public function test_publication_with_specific_published_at(): void /** @var ArticlePublication $publication */ $publication = ArticlePublication::factory()->create(['published_at' => $timestamp]); - $this->assertInstanceOf(\Carbon\Carbon::class, $publication->published_at); + $this->assertInstanceOf(Carbon::class, $publication->published_at); $this->assertEquals($timestamp->format('Y-m-d H:i:s'), $publication->published_at->format('Y-m-d H:i:s')); } @@ -230,8 +231,8 @@ public function test_publication_timestamps(): void $this->assertNotNull($publication->created_at); $this->assertNotNull($publication->updated_at); - $this->assertInstanceOf(\Carbon\Carbon::class, $publication->created_at); - $this->assertInstanceOf(\Carbon\Carbon::class, $publication->updated_at); + $this->assertInstanceOf(Carbon::class, $publication->created_at); + $this->assertInstanceOf(Carbon::class, $publication->updated_at); } public function test_multiple_publications_for_same_article(): void diff --git a/tests/Unit/Models/ArticleTest.php b/tests/Unit/Models/ArticleTest.php index ead0e8b..0f2a538 100644 --- a/tests/Unit/Models/ArticleTest.php +++ b/tests/Unit/Models/ArticleTest.php @@ -6,6 +6,7 @@ use App\Models\Article; use App\Models\Feed; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Support\Carbon; use Illuminate\Support\Facades\Event; use Illuminate\Support\Facades\Http; use Tests\TestCase; @@ -70,6 +71,6 @@ public function test_validated_at_is_cast_to_datetime(): void 'validated_at' => now(), ]); - $this->assertInstanceOf(\Illuminate\Support\Carbon::class, $article->validated_at); + $this->assertInstanceOf(Carbon::class, $article->validated_at); } } diff --git a/tests/Unit/Models/FeedTest.php b/tests/Unit/Models/FeedTest.php index 05864cb..274659c 100644 --- a/tests/Unit/Models/FeedTest.php +++ b/tests/Unit/Models/FeedTest.php @@ -7,6 +7,7 @@ use App\Models\Language; use App\Models\PlatformChannel; use App\Models\Route; +use Carbon\Carbon; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; @@ -51,7 +52,7 @@ public function test_casts_last_fetched_at_to_datetime(): void $timestamp = now()->subHours(2); $feed = Feed::factory()->create(['last_fetched_at' => $timestamp]); - $this->assertInstanceOf(\Carbon\Carbon::class, $feed->last_fetched_at); + $this->assertInstanceOf(Carbon::class, $feed->last_fetched_at); $this->assertEquals($timestamp->format('Y-m-d H:i:s'), $feed->last_fetched_at->format('Y-m-d H:i:s')); } @@ -376,7 +377,7 @@ public function test_feed_timestamps(): void $this->assertNotNull($feed->created_at); $this->assertNotNull($feed->updated_at); - $this->assertInstanceOf(\Carbon\Carbon::class, $feed->created_at); - $this->assertInstanceOf(\Carbon\Carbon::class, $feed->updated_at); + $this->assertInstanceOf(Carbon::class, $feed->created_at); + $this->assertInstanceOf(Carbon::class, $feed->updated_at); } } diff --git a/tests/Unit/Models/KeywordTest.php b/tests/Unit/Models/KeywordTest.php index d1fbd13..d729ad2 100644 --- a/tests/Unit/Models/KeywordTest.php +++ b/tests/Unit/Models/KeywordTest.php @@ -5,6 +5,8 @@ use App\Models\Feed; use App\Models\Keyword; use App\Models\PlatformChannel; +use Carbon\Carbon; +use Illuminate\Database\QueryException; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; @@ -213,7 +215,7 @@ public function test_keyword_uniqueness_constraint(): void ]); // Attempt to create duplicate should fail - $this->expectException(\Illuminate\Database\QueryException::class); + $this->expectException(QueryException::class); Keyword::create([ 'feed_id' => $feed->id, @@ -257,8 +259,8 @@ public function test_keyword_timestamps(): void $this->assertNotNull($keyword->created_at); $this->assertNotNull($keyword->updated_at); - $this->assertInstanceOf(\Carbon\Carbon::class, $keyword->created_at); - $this->assertInstanceOf(\Carbon\Carbon::class, $keyword->updated_at); + $this->assertInstanceOf(Carbon::class, $keyword->created_at); + $this->assertInstanceOf(Carbon::class, $keyword->updated_at); } public function test_keyword_default_active_state(): void diff --git a/tests/Unit/Models/LanguageTest.php b/tests/Unit/Models/LanguageTest.php index 3017be0..d18baf0 100644 --- a/tests/Unit/Models/LanguageTest.php +++ b/tests/Unit/Models/LanguageTest.php @@ -6,6 +6,7 @@ use App\Models\Language; use App\Models\PlatformChannel; use App\Models\PlatformInstance; +use Carbon\Carbon; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; @@ -193,8 +194,8 @@ public function test_language_timestamps(): void $this->assertNotNull($language->created_at); $this->assertNotNull($language->updated_at); - $this->assertInstanceOf(\Carbon\Carbon::class, $language->created_at); - $this->assertInstanceOf(\Carbon\Carbon::class, $language->updated_at); + $this->assertInstanceOf(Carbon::class, $language->created_at); + $this->assertInstanceOf(Carbon::class, $language->updated_at); } public function test_language_can_have_multiple_platform_instances(): void diff --git a/tests/Unit/Models/PlatformAccountTest.php b/tests/Unit/Models/PlatformAccountTest.php index c3e351e..ff58aca 100644 --- a/tests/Unit/Models/PlatformAccountTest.php +++ b/tests/Unit/Models/PlatformAccountTest.php @@ -5,6 +5,7 @@ use App\Enums\PlatformEnum; use App\Models\PlatformAccount; use App\Models\PlatformChannel; +use Carbon\Carbon; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; @@ -65,7 +66,7 @@ public function test_casts_last_tested_at_to_datetime(): void $timestamp = now()->subHours(2); $account = PlatformAccount::factory()->create(['last_tested_at' => $timestamp]); - $this->assertInstanceOf(\Carbon\Carbon::class, $account->last_tested_at); + $this->assertInstanceOf(Carbon::class, $account->last_tested_at); $this->assertEquals($timestamp->format('Y-m-d H:i:s'), $account->last_tested_at->format('Y-m-d H:i:s')); } @@ -366,8 +367,8 @@ public function test_account_timestamps(): void $this->assertNotNull($account->created_at); $this->assertNotNull($account->updated_at); - $this->assertInstanceOf(\Carbon\Carbon::class, $account->created_at); - $this->assertInstanceOf(\Carbon\Carbon::class, $account->updated_at); + $this->assertInstanceOf(Carbon::class, $account->created_at); + $this->assertInstanceOf(Carbon::class, $account->updated_at); } public function test_account_can_have_multiple_channels_with_different_priorities(): void diff --git a/tests/Unit/Models/PlatformChannelTest.php b/tests/Unit/Models/PlatformChannelTest.php index 9d08a2e..f6e81ba 100644 --- a/tests/Unit/Models/PlatformChannelTest.php +++ b/tests/Unit/Models/PlatformChannelTest.php @@ -8,6 +8,7 @@ use App\Models\PlatformChannel; use App\Models\PlatformInstance; use App\Models\Route; +use Carbon\Carbon; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; @@ -305,8 +306,8 @@ public function test_channel_timestamps(): void $this->assertNotNull($channel->created_at); $this->assertNotNull($channel->updated_at); - $this->assertInstanceOf(\Carbon\Carbon::class, $channel->created_at); - $this->assertInstanceOf(\Carbon\Carbon::class, $channel->updated_at); + $this->assertInstanceOf(Carbon::class, $channel->created_at); + $this->assertInstanceOf(Carbon::class, $channel->updated_at); } public function test_channel_can_have_multiple_accounts_with_different_priorities(): void diff --git a/tests/Unit/Models/PlatformInstanceTest.php b/tests/Unit/Models/PlatformInstanceTest.php index 296515f..7ec68d3 100644 --- a/tests/Unit/Models/PlatformInstanceTest.php +++ b/tests/Unit/Models/PlatformInstanceTest.php @@ -6,6 +6,7 @@ use App\Models\Language; use App\Models\PlatformChannel; use App\Models\PlatformInstance; +use Carbon\Carbon; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; @@ -250,8 +251,8 @@ public function test_instance_timestamps(): void $this->assertNotNull($instance->created_at); $this->assertNotNull($instance->updated_at); - $this->assertInstanceOf(\Carbon\Carbon::class, $instance->created_at); - $this->assertInstanceOf(\Carbon\Carbon::class, $instance->updated_at); + $this->assertInstanceOf(Carbon::class, $instance->created_at); + $this->assertInstanceOf(Carbon::class, $instance->updated_at); } public function test_instance_can_have_multiple_languages(): void diff --git a/tests/Unit/Models/RouteArticleTest.php b/tests/Unit/Models/RouteArticleTest.php index f5229e9..97b656e 100644 --- a/tests/Unit/Models/RouteArticleTest.php +++ b/tests/Unit/Models/RouteArticleTest.php @@ -8,6 +8,7 @@ use App\Models\PlatformChannel; use App\Models\Route; use App\Models\RouteArticle; +use Illuminate\Database\QueryException; use Illuminate\Foundation\Testing\RefreshDatabase; use Tests\TestCase; @@ -104,7 +105,7 @@ public function test_unique_constraint_prevents_duplicate_route_articles(): void RouteArticle::factory()->forRoute($route)->create(['article_id' => $article->id]); - $this->expectException(\Illuminate\Database\QueryException::class); + $this->expectException(QueryException::class); RouteArticle::factory()->forRoute($route)->create(['article_id' => $article->id]); } diff --git a/tests/Unit/Services/ArticleFetcherRssTest.php b/tests/Unit/Services/ArticleFetcherRssTest.php index 425ae23..3f15dd6 100644 --- a/tests/Unit/Services/ArticleFetcherRssTest.php +++ b/tests/Unit/Services/ArticleFetcherRssTest.php @@ -5,6 +5,7 @@ use App\Models\Article; use App\Models\Feed; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\Http; use Mockery; use Tests\TestCase; @@ -56,7 +57,7 @@ public function test_get_articles_from_rss_feed_returns_collection(): void $fetcher = $this->createArticleFetcher(); $result = $fetcher->getArticlesFromFeed($feed); - $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + $this->assertInstanceOf(Collection::class, $result); } public function test_get_articles_from_rss_feed_creates_articles(): void @@ -118,7 +119,7 @@ public function test_get_articles_from_rss_feed_handles_invalid_xml(): void $fetcher = $this->createArticleFetcher(); $result = $fetcher->getArticlesFromFeed($feed); - $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + $this->assertInstanceOf(Collection::class, $result); $this->assertEmpty($result); } diff --git a/tests/Unit/Services/ArticleFetcherTest.php b/tests/Unit/Services/ArticleFetcherTest.php index 180b099..f281bea 100644 --- a/tests/Unit/Services/ArticleFetcherTest.php +++ b/tests/Unit/Services/ArticleFetcherTest.php @@ -6,6 +6,7 @@ use App\Models\Feed; use App\Services\Article\ArticleFetcher; use Illuminate\Foundation\Testing\RefreshDatabase; +use Illuminate\Support\Collection; use Illuminate\Support\Facades\Http; use Mockery; use Tests\TestCase; @@ -38,7 +39,7 @@ public function test_get_articles_from_feed_returns_collection(): void $result = $articleFetcher->getArticlesFromFeed($feed); - $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + $this->assertInstanceOf(Collection::class, $result); } public function test_get_articles_from_rss_feed_returns_empty_collection(): void @@ -66,7 +67,7 @@ public function test_get_articles_from_website_feed_handles_no_parser(): void $result = $articleFetcher->getArticlesFromFeed($feed); // Should return empty collection when no parser is available - $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + $this->assertInstanceOf(Collection::class, $result); $this->assertEmpty($result); } @@ -80,7 +81,7 @@ public function test_get_articles_from_unsupported_feed_type(): void $articleFetcher = $this->createArticleFetcher(); $result = $articleFetcher->getArticlesFromFeed($feed); - $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + $this->assertInstanceOf(Collection::class, $result); $this->assertEmpty($result); } @@ -130,7 +131,7 @@ public function test_get_articles_from_feed_with_null_feed_type(): void $articleFetcher = $this->createArticleFetcher(); $result = $articleFetcher->getArticlesFromFeed($feed); - $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + $this->assertInstanceOf(Collection::class, $result); $this->assertEmpty($result); } @@ -150,7 +151,7 @@ public function test_get_articles_from_website_feed_with_supported_parser(): voi $articleFetcher = $this->createArticleFetcher(); $result = $articleFetcher->getArticlesFromFeed($feed); - $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + $this->assertInstanceOf(Collection::class, $result); // VRT parser will process the mocked HTML response } @@ -166,7 +167,7 @@ public function test_get_articles_from_website_feed_handles_invalid_url(): void $articleFetcher = $this->createArticleFetcher(); $result = $articleFetcher->getArticlesFromFeed($feed); - $this->assertInstanceOf(\Illuminate\Support\Collection::class, $result); + $this->assertInstanceOf(Collection::class, $result); $this->assertEmpty($result); } diff --git a/tests/Unit/Services/Http/HttpFetcherTest.php b/tests/Unit/Services/Http/HttpFetcherTest.php index 7f6c8c9..ae2266b 100644 --- a/tests/Unit/Services/Http/HttpFetcherTest.php +++ b/tests/Unit/Services/Http/HttpFetcherTest.php @@ -4,6 +4,8 @@ use App\Services\Http\HttpFetcher; use Exception; +use GuzzleHttp\Exception\ConnectException; +use GuzzleHttp\Psr7\Request; use Illuminate\Http\Client\Response; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Log; @@ -154,7 +156,7 @@ public function test_fetch_multiple_urls_returns_empty_array_on_exception(): voi $urls = ['https://example.com']; Http::fake(function () { - throw new \GuzzleHttp\Exception\ConnectException('Pool request failed', new \GuzzleHttp\Psr7\Request('GET', 'https://example.com')); + throw new ConnectException('Pool request failed', new Request('GET', 'https://example.com')); }); $results = HttpFetcher::fetchMultipleUrls($urls); diff --git a/tests/Unit/Services/ValidationServiceTest.php b/tests/Unit/Services/ValidationServiceTest.php index 4d216d0..5133193 100644 --- a/tests/Unit/Services/ValidationServiceTest.php +++ b/tests/Unit/Services/ValidationServiceTest.php @@ -14,6 +14,7 @@ use App\Services\Article\ValidationService; use Illuminate\Foundation\Testing\RefreshDatabase; use Mockery; +use Mockery\MockInterface; use Tests\TestCase; class ValidationServiceTest extends TestCase @@ -22,7 +23,7 @@ class ValidationServiceTest extends TestCase private ValidationService $validationService; - private \Mockery\MockInterface $articleFetcher; + private MockInterface $articleFetcher; protected function setUp(): void {