미리보기 편집기는 설정을 시험해 보는 자리인데, 본문 동기화가 hasChanges 를 렌더를 일으키는 setLocal 로 올리면서 시험 입력만으로 [저장] 이 켜졌다. 어느 편집기가 저장 대상인지는 레이아웃만 알므로 핸들러가 필드명을 알아보게 하지 않고 trackChanges 선언으로 받는다 — 하드코딩하면 다른 확장이 같은 미리보기 패턴을 쓸 때 그대로 재발한다. 같은 결함이 형제 경로에도 있었다. 평문 폴백은 hasChanges 를 본문 배치 (render:false + selfManaged:true)에 실어, 편집기 자산을 못 불러온 환경에서 본문만 고치면 저장 버튼이 잠긴 채로 남았다 — 폐쇄망에서는 그 폴백이 정상 경로다. 폴백은 렌더 시점에도 같은 함수를 부르므로 화면을 여는 것만으로 변경됨이 되지 않도록, 사용자 입력에서 온 호출만 플래그를 올린다. components.json 생성기는 종결 개행을 PHP_EOL 로 써서 Windows 빌드마다 그 파일을 유령 변경으로 남겼다. 줄 내용이 같아 diff 가 비어 보이므로 무엇이 바뀐 것인지 알 수 없는 변경만 쌓인다.
106 lines
3.4 KiB
PHP
106 lines
3.4 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\Extension;
|
|
|
|
use App\Extension\Traits\GeneratesComponentManifest;
|
|
use Tests\TestCase;
|
|
|
|
/**
|
|
* components.json 종결 개행이 빌드 OS 에 좌우되지 않는지 확인합니다.
|
|
*
|
|
* 이 매니페스트는 `module:build` / `plugin:build` 산출물이면서 Git 추적 대상이다.
|
|
* 종결 개행을 PHP_EOL 로 쓰면 Windows 빌드에서만 "\r\n" 이 되어, 소스를 하나도
|
|
* 고치지 않고 다시 빌드하기만 해도 변경으로 잡힌다. 줄 내용은 같으므로 diff 는
|
|
* 비어 보이고, 무엇이 바뀐 것인지 알 수 없는 변경만 남는다.
|
|
*/
|
|
class GeneratesComponentManifestNewlineTest extends TestCase
|
|
{
|
|
private string $buildPath;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
$this->buildPath = sys_get_temp_dir().'/g7-cm-'.uniqid();
|
|
mkdir($this->buildPath.'/resources/js/components/basic', 0o777, true);
|
|
file_put_contents($this->buildPath.'/plugin.json', json_encode(['version' => '1.2.3']));
|
|
file_put_contents($this->buildPath.'/resources/js/components/basic/Foo.tsx', 'export const Foo = () => null;');
|
|
}
|
|
|
|
protected function tearDown(): void
|
|
{
|
|
$this->removeDirectory($this->buildPath);
|
|
|
|
parent::tearDown();
|
|
}
|
|
|
|
/**
|
|
* 트레이트를 쓰는 익명 클래스로 생성기를 호출합니다.
|
|
*
|
|
* @return array{written: bool, count: int, path: string} 작성 결과
|
|
*/
|
|
private function generate(): array
|
|
{
|
|
$generator = new class
|
|
{
|
|
use GeneratesComponentManifest;
|
|
|
|
/**
|
|
* protected 생성기를 테스트에서 호출하기 위한 통로입니다.
|
|
*
|
|
* @param string $buildPath 빌드 경로
|
|
* @return array{written: bool, count: int, path: string} 작성 결과
|
|
*/
|
|
public function run(string $buildPath): array
|
|
{
|
|
return $this->generateComponentManifest($buildPath, 'sirsoft-sample');
|
|
}
|
|
};
|
|
|
|
return $generator->run($this->buildPath);
|
|
}
|
|
|
|
/**
|
|
* 디렉토리를 재귀 삭제합니다.
|
|
*
|
|
* @param string $dir 삭제할 디렉토리
|
|
* @return void
|
|
*/
|
|
private function removeDirectory(string $dir): void
|
|
{
|
|
if (! is_dir($dir)) {
|
|
return;
|
|
}
|
|
|
|
foreach (scandir($dir) ?: [] as $entry) {
|
|
if ($entry === '.' || $entry === '..') {
|
|
continue;
|
|
}
|
|
$path = $dir.'/'.$entry;
|
|
is_dir($path) ? $this->removeDirectory($path) : @unlink($path);
|
|
}
|
|
|
|
@rmdir($dir);
|
|
}
|
|
|
|
public function test_manifest_ends_with_lf_not_platform_eol(): void
|
|
{
|
|
$result = $this->generate();
|
|
|
|
$this->assertTrue($result['written']);
|
|
|
|
$raw = file_get_contents($result['path']);
|
|
|
|
$this->assertStringEndsWith("}\n", $raw, 'LF 로 끝나야 한다');
|
|
$this->assertStringNotContainsString("\r", $raw, '어느 줄에도 CR 이 없어야 한다 — 있으면 Windows 빌드에서만 변경으로 잡힌다');
|
|
}
|
|
|
|
public function test_rebuilding_the_same_source_produces_identical_bytes(): void
|
|
{
|
|
$first = file_get_contents($this->generate()['path']);
|
|
$second = file_get_contents($this->generate()['path']);
|
|
|
|
$this->assertSame($first, $second, '같은 소스를 다시 빌드하면 바이트까지 같아야 한다');
|
|
}
|
|
}
|