true, 'verboseOutput' => true ]); $tmpFiles = []; $view = function(string $diff) use (&$tmpFiles): string { $f = tempnam(sys_get_temp_dir(), 'lbdiff_'); file_put_contents($f, $diff); $tmpFiles[] = $f; return (new DiffViewer($f))->displaySideBySide(); }; // の行を [クラス, 内容] の配列にする $cells = function(string $html): array { preg_match_all('#(.*?)#s', $html, $m, PREG_SET_ORDER); return array_map(fn($x) => [$x[1], $x[2]], $m); }; $test->describe('差分ビューア', function($test) use ($view, $cells): void { $test->it('無いファイルは例外のはず', function($test): void { $test->assertThrows(fn() => new DiffViewer('/no/such/file.diff'), \Exception::class); }); $test->it('git形式の差分を左右に並べるはず', function($test) use ($view, $cells): void { $html = $view("diff --git a/main.c b/main.c\nindex 1..2 100644\n--- a/main.c\n+++ b/main.c\n" ."@@ -1,3 +1,3 @@\n #include \n-int a;\n+int b;\n return 0;\n"); $test->assertStringContains('

ファイル: a/main.c | b/main.c

', $html); $test->assertStringContains('@@ -1,3 +1,3 @@', $html); $c = $cells($html); $test->assertEquals(['line-number', '1'], $c[0]); $test->assertEquals(['context', '#include <stdio.h>'], $c[1]); $test->assertEquals(['removed', 'int a;'], $c[5]); $test->assertEquals(['added', 'int b;'], $c[7]); $test->assertEquals(['line-number', '2'], $c[6]); }); $test->it('削除と追加の数が違う場合は空のセルで埋めるはず', function($test) use ($view): void { $html = $view("--- a.txt\n+++ b.txt\n@@ -1,2 +1,1 @@\n-x\n-y\n+z\n"); $test->assertStringContains(' ', $html); $test->assertEquals(1, substr_count($html, 'class="empty"')); }); $test->it('「---」で始まる削除行をファイルヘッダーと間違えないはず', function($test) use ($view): void { $html = $view("--- a/x.md\n+++ b/x.md\n@@ -1,2 +1,1 @@\n---- 区切り\n keep\n"); $test->assertEquals(1, substr_count($html, '

')); $test->assertStringContains('--- 区切り', $html); }); $test->it('行数が省略されたハンクと新しいファイルを扱えるはず', function($test) use ($view, $cells): void { $html = $view("diff --git a/new.txt b/new.txt\nnew file mode 100644\n--- /dev/null\n+++ b/new.txt\n@@ -0,0 +1 @@\n+hello\n\\ No newline at end of file\n"); $test->assertStringContains('

ファイル: /dev/null | b/new.txt

', $html); $c = $cells($html); $test->assertEquals(['added', 'hello'], $c[3]); $test->assertEquals(['line-number', '1'], $c[2]); }); $test->it('複数のファイルと内容の無い変更を扱えるはず', function($test) use ($view): void { $html = $view("diff --git a/a.png b/a.png\nBinary files a/a.png and b/a.png differ\n" ."diff --git a/old.sh b/new.sh\nsimilarity index 100%\nrename from old.sh\nrename to new.sh\n" ."diff --git a/c.txt b/c.txt\n--- a/c.txt\n+++ b/c.txt\n@@ -1 +1 @@\n-1\n+2\n"); $test->assertEquals(3, substr_count($html, '

')); $test->assertStringContains('

バイナリファイル

', $html); $test->assertStringContains('

ファイル: a/old.sh | b/new.sh

', $html); $test->assertStringContains('類似度:100% / 名前の変更元:old.sh / 名前の変更先:new.sh', $html); }); $test->it('HTMLをエスケープするはず', function($test) use ($view): void { $html = $view("--- a/.html\n+++ b/.html\n@@ -1 +1 @@\n-\n+&\n"); $test->assertFalse(str_contains($html, '