From e5c633600121333bec7426e6b7a5b903b62d7b85 Mon Sep 17 00:00:00 2001 From: Jordan Partridge Date: Fri, 12 Dec 2025 08:43:29 -0700 Subject: [PATCH] feat: return typed DTOs from files/checks/commits methods This change enhances type safety by returning strongly-typed DTOs instead of raw arrays from the files(), checks(), and commits() methods. Changes: - Created File DTO for file change information - Created Commit DTO for commit data - Created CommitAuthor DTO for git-level author/committer info - Updated files() to return File[] instead of array - Updated checks() to return CheckRun[] instead of array - Updated commits() to return Commit[] instead of array - Added comprehensive test coverage for all new DTOs - Updated existing tests to validate typed return values All DTOs follow the existing pattern with: - Readonly properties - fromArray() factory method - toArray() serialization method - Helper methods (isAdded(), isModified(), etc.) Fixes #5 --- src/DataTransferObjects/Commit.php | 46 +++++ src/DataTransferObjects/CommitAuthor.php | 34 ++++ src/DataTransferObjects/File.php | 76 ++++++++ src/PullRequest.php | 27 ++- .../DataTransferObjects/CommitAuthorTest.php | 35 ++++ tests/Unit/DataTransferObjects/CommitTest.php | 128 +++++++++++++ tests/Unit/DataTransferObjects/FileTest.php | 152 +++++++++++++++ tests/Unit/PullRequestWrapperTest.php | 179 +++++++++++++++++- 8 files changed, 663 insertions(+), 14 deletions(-) create mode 100644 src/DataTransferObjects/Commit.php create mode 100644 src/DataTransferObjects/CommitAuthor.php create mode 100644 src/DataTransferObjects/File.php create mode 100644 tests/Unit/DataTransferObjects/CommitAuthorTest.php create mode 100644 tests/Unit/DataTransferObjects/CommitTest.php create mode 100644 tests/Unit/DataTransferObjects/FileTest.php diff --git a/src/DataTransferObjects/Commit.php b/src/DataTransferObjects/Commit.php new file mode 100644 index 0000000..161454b --- /dev/null +++ b/src/DataTransferObjects/Commit.php @@ -0,0 +1,46 @@ + $this->sha, + 'commit' => [ + 'message' => $this->message, + 'author' => $this->author->toArray(), + 'committer' => $this->committer->toArray(), + ], + 'html_url' => $this->htmlUrl, + 'author' => $this->githubAuthor?->toArray(), + 'committer' => $this->githubCommitter?->toArray(), + ]; + } +} diff --git a/src/DataTransferObjects/CommitAuthor.php b/src/DataTransferObjects/CommitAuthor.php new file mode 100644 index 0000000..5982dbf --- /dev/null +++ b/src/DataTransferObjects/CommitAuthor.php @@ -0,0 +1,34 @@ + $this->name, + 'email' => $this->email, + 'date' => $this->date->format('c'), + ]; + } +} diff --git a/src/DataTransferObjects/File.php b/src/DataTransferObjects/File.php new file mode 100644 index 0000000..536e638 --- /dev/null +++ b/src/DataTransferObjects/File.php @@ -0,0 +1,76 @@ +status === 'added'; + } + + public function isRemoved(): bool + { + return $this->status === 'removed'; + } + + public function isModified(): bool + { + return $this->status === 'modified'; + } + + public function isRenamed(): bool + { + return $this->status === 'renamed'; + } + + public function toArray(): array + { + return [ + 'sha' => $this->sha, + 'filename' => $this->filename, + 'status' => $this->status, + 'additions' => $this->additions, + 'deletions' => $this->deletions, + 'changes' => $this->changes, + 'blob_url' => $this->blobUrl, + 'raw_url' => $this->rawUrl, + 'contents_url' => $this->contentsUrl, + 'patch' => $this->patch, + 'previous_filename' => $this->previousFilename, + ]; + } +} diff --git a/src/PullRequest.php b/src/PullRequest.php index 6214d42..abbc2bc 100644 --- a/src/PullRequest.php +++ b/src/PullRequest.php @@ -5,7 +5,10 @@ namespace ConduitUI\Pr; use ConduitUi\GitHubConnector\Connector; +use ConduitUI\Pr\DataTransferObjects\CheckRun; use ConduitUI\Pr\DataTransferObjects\Comment; +use ConduitUI\Pr\DataTransferObjects\Commit; +use ConduitUI\Pr\DataTransferObjects\File; use ConduitUI\Pr\DataTransferObjects\PullRequest as PullRequestData; use ConduitUI\Pr\DataTransferObjects\Review; use ConduitUI\Pr\Requests\AddIssueLabels; @@ -182,7 +185,7 @@ public function comments(): array } /** - * @return array> + * @return array */ public function files(): array { @@ -192,10 +195,14 @@ public function files(): array $this->data->number )); - return array_values($response->json()); + return array_values(array_map( + fn (array $data) => File::fromArray($data), + $response->json() + )); } /** +/** * Get the raw diff text for this pull request. */ public function diff(): string @@ -210,7 +217,7 @@ public function diff(): string } /** - * @return array> + * @return array */ public function checks(): array { @@ -220,13 +227,18 @@ public function checks(): array $this->data->head->sha )); - return $response->json()['check_runs'] ?? []; + $checkRuns = $response->json()['check_runs'] ?? []; + + return array_values(array_map( + fn (array $data) => CheckRun::fromArray($data), + $checkRuns + )); } /** * Get all commits in this pull request (paginated, fetches all pages). * - * @return array> + * @return array */ public function commits(): array { @@ -253,7 +265,10 @@ public function commits(): array $page++; } while (count($commits) === $perPage); - return array_values($allCommits); + return array_values(array_map( + fn (array $data) => Commit::fromArray($data), + $allCommits + )); } /** diff --git a/tests/Unit/DataTransferObjects/CommitAuthorTest.php b/tests/Unit/DataTransferObjects/CommitAuthorTest.php new file mode 100644 index 0000000..44c3757 --- /dev/null +++ b/tests/Unit/DataTransferObjects/CommitAuthorTest.php @@ -0,0 +1,35 @@ + 'John Doe', + 'email' => 'john@example.com', + 'date' => '2025-01-01T10:00:00Z', + ]; + + $author = CommitAuthor::fromArray($data); + + expect($author->name)->toBe('John Doe') + ->and($author->email)->toBe('john@example.com') + ->and($author->date)->toBeInstanceOf(DateTimeImmutable::class) + ->and($author->date->format('Y-m-d'))->toBe('2025-01-01'); +}); + +it('can convert commit author to array', function () { + $data = [ + 'name' => 'Jane Smith', + 'email' => 'jane@example.com', + 'date' => '2025-01-15T14:30:00Z', + ]; + + $author = CommitAuthor::fromArray($data); + $result = $author->toArray(); + + expect($result['name'])->toBe('Jane Smith') + ->and($result['email'])->toBe('jane@example.com') + ->and($result['date'])->toBe('2025-01-15T14:30:00+00:00'); +}); diff --git a/tests/Unit/DataTransferObjects/CommitTest.php b/tests/Unit/DataTransferObjects/CommitTest.php new file mode 100644 index 0000000..88cec50 --- /dev/null +++ b/tests/Unit/DataTransferObjects/CommitTest.php @@ -0,0 +1,128 @@ + 'abc123def456', + 'commit' => [ + 'message' => 'Initial commit', + 'author' => [ + 'name' => 'John Doe', + 'email' => 'john@example.com', + 'date' => '2025-01-01T10:00:00Z', + ], + 'committer' => [ + 'name' => 'Jane Smith', + 'email' => 'jane@example.com', + 'date' => '2025-01-01T10:05:00Z', + ], + ], + 'html_url' => 'https://github.com/owner/repo/commit/abc123def456', + 'author' => [ + 'id' => 1, + 'login' => 'johndoe', + 'avatar_url' => 'https://example.com/avatar.jpg', + 'html_url' => 'https://github.com/johndoe', + 'type' => 'User', + ], + 'committer' => [ + 'id' => 2, + 'login' => 'janesmith', + 'avatar_url' => 'https://example.com/avatar2.jpg', + 'html_url' => 'https://github.com/janesmith', + 'type' => 'User', + ], + ]; + + $commit = Commit::fromArray($data); + + expect($commit->sha)->toBe('abc123def456') + ->and($commit->message)->toBe('Initial commit') + ->and($commit->author)->toBeInstanceOf(CommitAuthor::class) + ->and($commit->author->name)->toBe('John Doe') + ->and($commit->author->email)->toBe('john@example.com') + ->and($commit->committer)->toBeInstanceOf(CommitAuthor::class) + ->and($commit->committer->name)->toBe('Jane Smith') + ->and($commit->htmlUrl)->toBe('https://github.com/owner/repo/commit/abc123def456') + ->and($commit->githubAuthor)->toBeInstanceOf(User::class) + ->and($commit->githubAuthor->login)->toBe('johndoe') + ->and($commit->githubCommitter)->toBeInstanceOf(User::class) + ->and($commit->githubCommitter->login)->toBe('janesmith'); +}); + +it('can create commit without github users', function () { + $data = [ + 'sha' => 'def456abc789', + 'commit' => [ + 'message' => 'Fix bug', + 'author' => [ + 'name' => 'External Author', + 'email' => 'external@example.com', + 'date' => '2025-01-02T11:00:00Z', + ], + 'committer' => [ + 'name' => 'External Committer', + 'email' => 'committer@example.com', + 'date' => '2025-01-02T11:05:00Z', + ], + ], + 'html_url' => 'https://github.com/owner/repo/commit/def456abc789', + ]; + + $commit = Commit::fromArray($data); + + expect($commit->sha)->toBe('def456abc789') + ->and($commit->message)->toBe('Fix bug') + ->and($commit->githubAuthor)->toBeNull() + ->and($commit->githubCommitter)->toBeNull(); +}); + +it('can convert commit to array', function () { + $data = [ + 'sha' => 'abc123', + 'commit' => [ + 'message' => 'Test commit', + 'author' => [ + 'name' => 'Test Author', + 'email' => 'test@example.com', + 'date' => '2025-01-01T12:00:00Z', + ], + 'committer' => [ + 'name' => 'Test Committer', + 'email' => 'committer@example.com', + 'date' => '2025-01-01T12:05:00Z', + ], + ], + 'html_url' => 'https://github.com/owner/repo/commit/abc123', + 'author' => [ + 'id' => 1, + 'login' => 'testuser', + 'avatar_url' => 'https://example.com/avatar.jpg', + 'html_url' => 'https://github.com/testuser', + 'type' => 'User', + ], + 'committer' => [ + 'id' => 2, + 'login' => 'testcommitter', + 'avatar_url' => 'https://example.com/avatar2.jpg', + 'html_url' => 'https://github.com/testcommitter', + 'type' => 'User', + ], + ]; + + $commit = Commit::fromArray($data); + $result = $commit->toArray(); + + expect($result['sha'])->toBe('abc123') + ->and($result['commit']['message'])->toBe('Test commit') + ->and($result['commit']['author']['name'])->toBe('Test Author') + ->and($result['commit']['committer']['name'])->toBe('Test Committer') + ->and($result['html_url'])->toBe('https://github.com/owner/repo/commit/abc123') + ->and($result['author']['login'])->toBe('testuser') + ->and($result['committer']['login'])->toBe('testcommitter'); +}); diff --git a/tests/Unit/DataTransferObjects/FileTest.php b/tests/Unit/DataTransferObjects/FileTest.php new file mode 100644 index 0000000..e3ef776 --- /dev/null +++ b/tests/Unit/DataTransferObjects/FileTest.php @@ -0,0 +1,152 @@ + 'abc123', + 'filename' => 'src/Example.php', + 'status' => 'modified', + 'additions' => 10, + 'deletions' => 5, + 'changes' => 15, + 'blob_url' => 'https://github.com/owner/repo/blob/abc123/src/Example.php', + 'raw_url' => 'https://github.com/owner/repo/raw/abc123/src/Example.php', + 'contents_url' => 'https://api.github.com/repos/owner/repo/contents/src/Example.php', + 'patch' => '@@ -1,5 +1,10 @@', + ]; + + $file = File::fromArray($data); + + expect($file->sha)->toBe('abc123') + ->and($file->filename)->toBe('src/Example.php') + ->and($file->status)->toBe('modified') + ->and($file->additions)->toBe(10) + ->and($file->deletions)->toBe(5) + ->and($file->changes)->toBe(15) + ->and($file->blobUrl)->toBe('https://github.com/owner/repo/blob/abc123/src/Example.php') + ->and($file->rawUrl)->toBe('https://github.com/owner/repo/raw/abc123/src/Example.php') + ->and($file->contentsUrl)->toBe('https://api.github.com/repos/owner/repo/contents/src/Example.php') + ->and($file->patch)->toBe('@@ -1,5 +1,10 @@') + ->and($file->previousFilename)->toBeNull(); +}); + +it('can create file with optional fields', function () { + $data = [ + 'sha' => 'def456', + 'filename' => 'src/NewName.php', + 'status' => 'renamed', + 'additions' => 0, + 'deletions' => 0, + 'changes' => 0, + 'blob_url' => 'https://github.com/owner/repo/blob/def456/src/NewName.php', + 'raw_url' => 'https://github.com/owner/repo/raw/def456/src/NewName.php', + 'contents_url' => 'https://api.github.com/repos/owner/repo/contents/src/NewName.php', + 'previous_filename' => 'src/OldName.php', + ]; + + $file = File::fromArray($data); + + expect($file->previousFilename)->toBe('src/OldName.php') + ->and($file->patch)->toBeNull(); +}); + +it('can check if file is added', function () { + $file = File::fromArray([ + 'sha' => 'abc123', + 'filename' => 'new.php', + 'status' => 'added', + 'additions' => 10, + 'deletions' => 0, + 'changes' => 10, + 'blob_url' => 'https://example.com', + 'raw_url' => 'https://example.com', + 'contents_url' => 'https://example.com', + ]); + + expect($file->isAdded())->toBeTrue() + ->and($file->isRemoved())->toBeFalse() + ->and($file->isModified())->toBeFalse() + ->and($file->isRenamed())->toBeFalse(); +}); + +it('can check if file is removed', function () { + $file = File::fromArray([ + 'sha' => 'abc123', + 'filename' => 'deleted.php', + 'status' => 'removed', + 'additions' => 0, + 'deletions' => 10, + 'changes' => 10, + 'blob_url' => 'https://example.com', + 'raw_url' => 'https://example.com', + 'contents_url' => 'https://example.com', + ]); + + expect($file->isRemoved())->toBeTrue() + ->and($file->isAdded())->toBeFalse() + ->and($file->isModified())->toBeFalse() + ->and($file->isRenamed())->toBeFalse(); +}); + +it('can check if file is modified', function () { + $file = File::fromArray([ + 'sha' => 'abc123', + 'filename' => 'changed.php', + 'status' => 'modified', + 'additions' => 5, + 'deletions' => 3, + 'changes' => 8, + 'blob_url' => 'https://example.com', + 'raw_url' => 'https://example.com', + 'contents_url' => 'https://example.com', + ]); + + expect($file->isModified())->toBeTrue() + ->and($file->isAdded())->toBeFalse() + ->and($file->isRemoved())->toBeFalse() + ->and($file->isRenamed())->toBeFalse(); +}); + +it('can check if file is renamed', function () { + $file = File::fromArray([ + 'sha' => 'abc123', + 'filename' => 'new.php', + 'status' => 'renamed', + 'additions' => 0, + 'deletions' => 0, + 'changes' => 0, + 'blob_url' => 'https://example.com', + 'raw_url' => 'https://example.com', + 'contents_url' => 'https://example.com', + 'previous_filename' => 'old.php', + ]); + + expect($file->isRenamed())->toBeTrue() + ->and($file->isAdded())->toBeFalse() + ->and($file->isRemoved())->toBeFalse() + ->and($file->isModified())->toBeFalse(); +}); + +it('can convert file to array', function () { + $data = [ + 'sha' => 'abc123', + 'filename' => 'test.php', + 'status' => 'modified', + 'additions' => 10, + 'deletions' => 5, + 'changes' => 15, + 'blob_url' => 'https://example.com/blob', + 'raw_url' => 'https://example.com/raw', + 'contents_url' => 'https://example.com/contents', + 'patch' => '@@ patch @@', + 'previous_filename' => 'old.php', + ]; + + $file = File::fromArray($data); + $result = $file->toArray(); + + expect($result)->toBe($data); +}); diff --git a/tests/Unit/PullRequestWrapperTest.php b/tests/Unit/PullRequestWrapperTest.php index 0648b74..eaae286 100644 --- a/tests/Unit/PullRequestWrapperTest.php +++ b/tests/Unit/PullRequestWrapperTest.php @@ -3,7 +3,10 @@ declare(strict_types=1); use ConduitUi\GitHubConnector\Connector; +use ConduitUI\Pr\DataTransferObjects\CheckRun; use ConduitUI\Pr\DataTransferObjects\Comment; +use ConduitUI\Pr\DataTransferObjects\Commit; +use ConduitUI\Pr\DataTransferObjects\File; use ConduitUI\Pr\DataTransferObjects\PullRequest as PullRequestData; use ConduitUI\Pr\PullRequest; use Saloon\Http\Request; @@ -124,13 +127,35 @@ function createTestPullRequestData(): PullRequestData 'sha' => 'commit1', 'commit' => [ 'message' => 'First commit', + 'author' => [ + 'name' => 'Author 1', + 'email' => 'author1@example.com', + 'date' => '2025-01-01T10:00:00Z', + ], + 'committer' => [ + 'name' => 'Committer 1', + 'email' => 'committer1@example.com', + 'date' => '2025-01-01T10:05:00Z', + ], ], + 'html_url' => 'https://github.com/owner/repo/commit/commit1', ], [ 'sha' => 'commit2', 'commit' => [ 'message' => 'Second commit', + 'author' => [ + 'name' => 'Author 2', + 'email' => 'author2@example.com', + 'date' => '2025-01-01T11:00:00Z', + ], + 'committer' => [ + 'name' => 'Committer 2', + 'email' => 'committer2@example.com', + 'date' => '2025-01-01T11:05:00Z', + ], ], + 'html_url' => 'https://github.com/owner/repo/commit/commit2', ], ]; @@ -142,8 +167,12 @@ function createTestPullRequestData(): PullRequestData expect($commits)->toBeArray() ->and($commits)->toHaveCount(2) - ->and($commits[0]['sha'])->toBe('commit1') - ->and($commits[1]['sha'])->toBe('commit2'); + ->and($commits[0])->toBeInstanceOf(Commit::class) + ->and($commits[0]->sha)->toBe('commit1') + ->and($commits[0]->message)->toBe('First commit') + ->and($commits[1])->toBeInstanceOf(Commit::class) + ->and($commits[1]->sha)->toBe('commit2') + ->and($commits[1]->message)->toBe('Second commit'); }); it('returns empty array when no commits', function () { @@ -220,13 +249,39 @@ function createTestPullRequestData(): PullRequestData // First page: 100 commits (full page triggers next request) $page1 = array_map(fn ($i) => [ 'sha' => "commit-page1-{$i}", - 'commit' => ['message' => "Commit {$i}"], + 'commit' => [ + 'message' => "Commit {$i}", + 'author' => [ + 'name' => "Author {$i}", + 'email' => "author{$i}@example.com", + 'date' => '2025-01-01T10:00:00Z', + ], + 'committer' => [ + 'name' => "Committer {$i}", + 'email' => "committer{$i}@example.com", + 'date' => '2025-01-01T10:05:00Z', + ], + ], + 'html_url' => "https://github.com/owner/repo/commit/commit-page1-{$i}", ], range(1, 100)); // Second page: 50 commits (partial page, stops pagination) $page2 = array_map(fn ($i) => [ 'sha' => "commit-page2-{$i}", - 'commit' => ['message' => "Commit {$i}"], + 'commit' => [ + 'message' => "Commit {$i}", + 'author' => [ + 'name' => "Author {$i}", + 'email' => "author{$i}@example.com", + 'date' => '2025-01-01T10:00:00Z', + ], + 'committer' => [ + 'name' => "Committer {$i}", + 'email' => "committer{$i}@example.com", + 'date' => '2025-01-01T10:05:00Z', + ], + ], + 'html_url' => "https://github.com/owner/repo/commit/commit-page2-{$i}", ], range(1, 50)); $connector = createMockConnector([$page1, $page2]); @@ -237,10 +292,14 @@ function createTestPullRequestData(): PullRequestData expect($commits)->toBeArray() ->and($commits)->toHaveCount(150) - ->and($commits[0]['sha'])->toBe('commit-page1-1') - ->and($commits[99]['sha'])->toBe('commit-page1-100') - ->and($commits[100]['sha'])->toBe('commit-page2-1') - ->and($commits[149]['sha'])->toBe('commit-page2-50'); + ->and($commits[0])->toBeInstanceOf(Commit::class) + ->and($commits[0]->sha)->toBe('commit-page1-1') + ->and($commits[99])->toBeInstanceOf(Commit::class) + ->and($commits[99]->sha)->toBe('commit-page1-100') + ->and($commits[100])->toBeInstanceOf(Commit::class) + ->and($commits[100]->sha)->toBe('commit-page2-1') + ->and($commits[149])->toBeInstanceOf(Commit::class) + ->and($commits[149]->sha)->toBe('commit-page2-50'); }); it('paginates issue comments across multiple pages', function () { @@ -312,4 +371,108 @@ function createTestPullRequestData(): PullRequestData expect($diff)->toBeString() ->and($diff)->toContain('diff --git') ->and($diff)->toContain('echo "Hello World"'); + $mockFiles = [ + [ + 'sha' => 'abc123', + 'filename' => 'src/Example.php', + 'status' => 'modified', + 'additions' => 10, + 'deletions' => 5, + 'changes' => 15, + 'blob_url' => 'https://github.com/owner/repo/blob/abc123/src/Example.php', + 'raw_url' => 'https://github.com/owner/repo/raw/abc123/src/Example.php', + 'contents_url' => 'https://api.github.com/repos/owner/repo/contents/src/Example.php', + 'patch' => '@@ -1,5 +1,10 @@', + ], + [ + 'sha' => 'def456', + 'filename' => 'tests/ExampleTest.php', + 'status' => 'added', + 'additions' => 20, + 'deletions' => 0, + 'changes' => 20, + 'blob_url' => 'https://github.com/owner/repo/blob/def456/tests/ExampleTest.php', + 'raw_url' => 'https://github.com/owner/repo/raw/def456/tests/ExampleTest.php', + 'contents_url' => 'https://api.github.com/repos/owner/repo/contents/tests/ExampleTest.php', + 'patch' => '@@ -0,0 +1,20 @@', + ], + ]; + + $connector = createMockConnector([$mockFiles]); + $prData = createTestPullRequestData(); + $pr = new PullRequest($connector, 'owner', 'repo', $prData); + + $files = $pr->files(); + + expect($files)->toBeArray() + ->and($files)->toHaveCount(2) + ->and($files[0])->toBeInstanceOf(File::class) + ->and($files[0]->filename)->toBe('src/Example.php') + ->and($files[0]->status)->toBe('modified') + ->and($files[0]->additions)->toBe(10) + ->and($files[1])->toBeInstanceOf(File::class) + ->and($files[1]->filename)->toBe('tests/ExampleTest.php') + ->and($files[1]->status)->toBe('added'); +}); + +it('returns empty array when no files', function () { + $connector = createMockConnector([[]]); + $prData = createTestPullRequestData(); + $pr = new PullRequest($connector, 'owner', 'repo', $prData); + + $files = $pr->files(); + + expect($files)->toBeArray() + ->and($files)->toBeEmpty(); +}); + +it('can get checks from pull request', function () { + $mockChecks = [ + 'check_runs' => [ + [ + 'id' => 1, + 'name' => 'PHPStan', + 'status' => 'completed', + 'conclusion' => 'success', + 'html_url' => 'https://github.com/owner/repo/runs/1', + 'started_at' => '2025-01-01T10:00:00Z', + 'completed_at' => '2025-01-01T10:05:00Z', + ], + [ + 'id' => 2, + 'name' => 'Pest', + 'status' => 'completed', + 'conclusion' => 'failure', + 'html_url' => 'https://github.com/owner/repo/runs/2', + 'started_at' => '2025-01-01T10:01:00Z', + 'completed_at' => '2025-01-01T10:06:00Z', + ], + ], + ]; + + $connector = createMockConnector([$mockChecks]); + $prData = createTestPullRequestData(); + $pr = new PullRequest($connector, 'owner', 'repo', $prData); + + $checks = $pr->checks(); + + expect($checks)->toBeArray() + ->and($checks)->toHaveCount(2) + ->and($checks[0])->toBeInstanceOf(CheckRun::class) + ->and($checks[0]->name)->toBe('PHPStan') + ->and($checks[0]->conclusion)->toBe('success') + ->and($checks[1])->toBeInstanceOf(CheckRun::class) + ->and($checks[1]->name)->toBe('Pest') + ->and($checks[1]->conclusion)->toBe('failure'); +}); + +it('returns empty array when no checks', function () { + $connector = createMockConnector([[]]); + $prData = createTestPullRequestData(); + $pr = new PullRequest($connector, 'owner', 'repo', $prData); + + $checks = $pr->checks(); + + expect($checks)->toBeArray() + ->and($checks)->toBeEmpty(); });