Files
ulthon_admin/tests/Unit/AdminUpdateServiceOptionalFilesTest.php

82 lines
3.9 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
declare(strict_types=1);
namespace tests\Unit;
use app\admin\service\AdminUpdateService;
use PHPUnit\Framework\TestCase;
/**
* AdminUpdateServiceBase::testIsOptionalFiles 分类矩阵单元测试(纯单元,不触 DB).
*
* 锚定 .agents 项目自维护文件改判"可选更新"的行为:
* - .agents/PROJECT.md(精确匹配)与 .agents/rules/project- 前缀文件属项目自维护,
* 升级时必须判为可选(optional=true),防止被强制覆盖/强制删除
* - .agents 其余内容(ulthon-* 规则、skills、非精确路径、无连字符文件名)保持强制(false)
*
* 22 用例 = 可选 12 + 强制 10。用 PHPUnit 10 属性式 DataProvider(不支持 @dataProvider 注解),
* 每个用例独立成测试,红/绿状态可逐例观察。
*/
class AdminUpdateServiceOptionalFilesTest extends TestCase
{
/**
* 通过匿名类暴露 protected testIsOptionalFiles(构造函数仅设常量属性,无副作用).
*/
private function makeExposer(): object
{
return new class extends AdminUpdateService {
public function expose(string $path): bool
{
return $this->testIsOptionalFiles($path);
}
};
}
public static function classificationProvider(): iterable
{
// 可选(true) 12 例:既有规则覆盖 8 例 + .agents 项目自维护新规则 4 例
yield 'optional: root AGENTS.md' => ['AGENTS.md', true];
yield 'optional: root composer.json' => ['composer.json', true];
yield 'optional: root .php-cs-fixer.php' => ['.php-cs-fixer.php', true];
yield 'optional: app prefix' => ['app/common/service/X.php', true];
yield 'optional: config prefix' => ['config/app.php', true];
yield 'optional: route prefix' => ['route/app.php', true];
yield 'optional: source/docker prefix' => ['source/docker/Dockerfile', true];
yield 'optional: extend/think prefix' => ['extend/think/store/X.php', true];
yield 'optional: .agents/PROJECT.md exact' => ['.agents/PROJECT.md', true];
yield 'optional: project rule flat' => ['.agents/rules/project-dev-runtime-deploy.md', true];
yield 'optional: project rule flat 2' => ['.agents/rules/project-account-system.md', true];
yield 'optional: project rule nested' => ['.agents/rules/project-deploy-detail/sub.md', true];
// 强制(false) 10 例:核心入口、框架内核、静态资源、迁移、.agents 其余内容
yield 'force: think entry' => ['think', false];
yield 'force: extend/base kernel' => ['extend/base/admin/service/AdminUpdateServiceBase.php', false];
yield 'force: public static' => ['public/static/common/css/a.css', false];
yield 'force: database migrations' => ['database/migrations/2024.php', false];
yield 'force: ulthon rule' => ['.agents/rules/ulthon-naming-convention.md', false];
yield 'force: ulthon skill' => ['.agents/skills/ulthon-timer/SKILL.md', false];
yield 'force: project skill (skills 始终强制)' => ['.agents/skills/project-x/SKILL.md', false];
yield 'force: project.md 无连字符不匹配前缀' => ['.agents/rules/project.md', false];
yield 'force: .agents/PROJECT 非精确不匹配' => ['.agents/PROJECT/about.md', false];
yield 'force: .agents/rules/.README' => ['.agents/rules/.README', false];
}
#[\PHPUnit\Framework\Attributes\DataProvider('classificationProvider')]
public function test_classification(string $path, bool $expectedOptional): void
{
$exposer = $this->makeExposer();
$this->assertSame(
$expectedOptional,
$exposer->expose($path),
sprintf(
'路径 %s 分类不符:预期%s,实际%s',
$path,
$expectedOptional ? '可选(true)' : '强制(false)',
$expectedOptional ? '强制(false)' : '可选(true)'
)
);
}
}