Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion KNOWLEDGE_BASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ An app can use the same `/api/v1` for you with signed requests. It keeps an SSH

A signed request sees what the web shows you, such as your own pending commits. It can also, with the web's validation, moderation, and rate limits:

- read your account, logs, replies, notifications (including grouped activity), and starred commits;
- read your account, logs, replies (50 a page, or fewer with `limit`), notifications (including grouped activity), and starred commits;
- commit, reply, and quote, with images, and delete your commits;
- preview commit drafts without publishing them;
- follow or unfollow, mute or unmute, and block or unblock, and list who you muted and blocked;
Expand Down
2 changes: 1 addition & 1 deletion app/Http/Controllers/Api/CommitReplyController.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
{
public function index(ListApiCommitRepliesRequest $request, #[CurrentUser] User $user, Commit $commit, CommitRepliesQuery $replies): AnonymousResourceCollection
{
return CommitResource::collection($replies->paginate($commit, $user, $request->boolean('newest'))->withQueryString());
return CommitResource::collection($replies->paginate($commit, $user, $request->boolean('newest'), $request->integer('limit', CommitRepliesQuery::PER_PAGE))->withQueryString());
}
}
4 changes: 3 additions & 1 deletion app/Http/Requests/ListApiCommitRepliesRequest.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,16 @@ public function authorize(): Response
}

/**
* Newest first continues the next_cursor of a reply preview, as on the web.
* Newest first continues the next_cursor of a reply preview, as on the web, and a limit asks for fewer replies a
* page, as the web's threads do.
*
* @return array<string, list<string>>
*/
public function rules(): array
{
return [
'newest' => ['sometimes', 'boolean'],
'limit' => ['sometimes', 'integer', 'between:1,50'],
];
}
}
25 changes: 25 additions & 0 deletions tests/Feature/Controllers/Api/CommitReplyControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,31 @@
->assertJsonPath('data.*.body', ['Reply 1', 'Reply 0']);
});

it('lists fewer replies a page when asked, as the web does, and keeps asking on the next page', function (): void {
$parent = Commit::factory()->create();

Commit::factory()->for($parent, 'parent')->count(12)
->state(new Sequence(fn (Sequence $sequence): array => [
'body' => "Reply {$sequence->index}",
'created_at' => now()->subMinutes(100 - $sequence->index),
]))
->create();

$first = signedApiRequest($this->keyPair, 'GET', route('api-commit-reply.index', [$parent, 'limit' => 5]));

$first->assertOk()->assertJsonPath('data.*.body', ['Reply 0', 'Reply 1', 'Reply 2', 'Reply 3', 'Reply 4']);

signedApiRequest($this->keyPair, 'GET', (string) $first->json('links.next'))
->assertOk()
->assertJsonPath('data.*.body', ['Reply 5', 'Reply 6', 'Reply 7', 'Reply 8', 'Reply 9']);
});

it('rejects a page of replies outside 1 to 50', function (int $limit): void {
signedApiRequest($this->keyPair, 'GET', route('api-commit-reply.index', [Commit::factory()->create(), 'limit' => $limit]))
->assertUnprocessable()
->assertJsonValidationErrors('limit');
})->with([0, 51]);

it('hides the replies of commits the user may not see', function (): void {
$parent = Commit::factory()->pending()->create();
Commit::factory()->for($parent, 'parent')->create();
Expand Down