This commit is contained in:
2026-01-01 21:10:46 +08:00
parent 5c1b19c08a
commit 6c31ffa120
26 changed files with 1171 additions and 209 deletions

109
tests/FixtureHandler.php Normal file
View File

@@ -0,0 +1,109 @@
<?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;
}
}