110 lines
4.1 KiB
PHP
110 lines
4.1 KiB
PHP
<?php
|
||
|
||
/*
|
||
* Copyright (c) 2025, Антон Аксенов
|
||
* This file is part of m3u.su project
|
||
* MIT License: https://git.axenov.dev/IPTV/web/src/branch/master/LICENSE
|
||
*/
|
||
|
||
declare(strict_types=1);
|
||
|
||
namespace Tests;
|
||
|
||
use InvalidArgumentException;
|
||
|
||
trait FixtureHandler
|
||
{
|
||
/**
|
||
* Вычитывает содержимое файла строкой
|
||
*
|
||
* @param string $filepath
|
||
* @return string
|
||
* @throws InvalidArgumentException
|
||
*/
|
||
public function loadFixtureContent(string $filepath): string
|
||
{
|
||
$filepath = static::buildFixtureFilePath($filepath);
|
||
is_file($filepath) || throw new InvalidArgumentException('File not found: ' . $filepath);
|
||
|
||
return (string) file_get_contents($filepath);
|
||
}
|
||
|
||
/**
|
||
* Вычитывает .json файл в php-массив
|
||
*
|
||
* @param string $filepath
|
||
* @param string|null $key
|
||
* @return array
|
||
* @throws InvalidArgumentException
|
||
*/
|
||
protected function loadJsonFixture(string $filepath, ?string $key = null): array
|
||
{
|
||
$contents = $this->loadFixtureContent($filepath);
|
||
$contents = json_decode($contents, true);
|
||
|
||
return $key ? $contents[$key] : $contents;
|
||
}
|
||
|
||
/**
|
||
* Подгружает фиксутуру для тестов
|
||
*
|
||
* @param string $filepath Имя файла или путь до него внутри tests/Fixtures/...
|
||
* @return mixed
|
||
* @throws InvalidArgumentException
|
||
*/
|
||
protected function loadPhpFixture(string $filepath): mixed
|
||
{
|
||
$filepath = static::buildFixtureFilePath($filepath);
|
||
is_file($filepath) || throw new InvalidArgumentException('File not found: ' . $filepath);
|
||
|
||
return require $filepath;
|
||
}
|
||
|
||
/**
|
||
* Сохраняет указанные сырые данные в виде файла с данными
|
||
* для использования в качестве фикстуры в тестах.
|
||
*
|
||
* Использование:
|
||
* 0. предполагается при подготовке к написанию теста
|
||
* 1. вызвать `makeFixture()`, передав нужные данные
|
||
* 2. найти файл в `tests/Fixtures/...`, проверить корректность
|
||
* 3. подгрузить фикстуру и замокать вызов курсорной БД-функции
|
||
* ```
|
||
* $fixture = this->loadFixture(...);
|
||
* $this->mockDbCursor(...)->andReturn($fixture);
|
||
* ```
|
||
*
|
||
* @param array|Collection $data Данные для сохранения в фикстуре
|
||
* @param string $name Имя файла или путь до него внутри tests/Fixtures/...
|
||
* @param bool $is_json Сохранить в json-формате
|
||
*/
|
||
public static function saveFixture(mixed $data, string $name, bool $is_json = false): void
|
||
{
|
||
$data = match (true) {
|
||
$data instanceof Traversable => iterator_to_array($data),
|
||
default => $data,
|
||
};
|
||
if ($is_json) {
|
||
$string = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||
$ext = 'json';
|
||
} else {
|
||
$string = var_export($data, true);
|
||
$string = preg_replace("/(\n\\s+)?array\\s\\(/", '[', $string); // конвертим в короткий синтаксис
|
||
$string = str_replace([')', 'NULL'], [']', 'null'], $string); // остатки
|
||
$string = "<?php\n\ndeclare(strict_types=1);\n\nreturn {$string};\n"; // добавляем заголовок для файла
|
||
$ext = 'php';
|
||
}
|
||
$filepath = __DIR__ . "/Fixtures/{$name}.{$ext}";
|
||
!file_exists($filepath) && @mkdir(dirname($filepath), recursive: true);
|
||
$filepath = str_replace('/', DIRECTORY_SEPARATOR, $filepath);
|
||
file_put_contents($filepath, $string);
|
||
}
|
||
|
||
protected static function buildFixtureFilePath(string $filepath): string
|
||
{
|
||
$filepath = trim(ltrim($filepath, DIRECTORY_SEPARATOR));
|
||
|
||
return __DIR__ . DIRECTORY_SEPARATOR . 'Fixtures' . DIRECTORY_SEPARATOR . $filepath;
|
||
}
|
||
}
|