test(api): cover unsupported-type and mixed-batch inline media scenarios

- External URL that downloads (200) but isn't a supported media type → 422,
  nothing persisted (the type-rejection branch, distinct from a download 404).
- Mixed batch: an already-hosted item + an external URL both succeed → both kept
  in order, only the external one creates a Media row.
This commit is contained in:
Paulo Castellano 2026-06-28 21:15:01 -03:00
parent df891574f7
commit 41cb9b02a3

View file

@ -299,6 +299,61 @@
expect(Media::where('mediable_id', $this->workspace->id)->count())->toBe(0);
});
it('rejects creating a post when an external media url is not a supported type', function () {
$this->socialAccount->update(['is_active' => true]);
// Downloads fine (200) but the bytes are not a supported media type.
Http::fake(['cdn.example.com/notes.txt' => Http::response('just some text', 200)]);
$this->withHeaders(['Authorization' => 'Bearer '.$this->plainToken])
->postJson(route('api.posts.store'), [
'content' => 'Bad type post',
'media' => [['url' => 'https://cdn.example.com/notes.txt']],
'platforms' => [
['social_account_id' => $this->socialAccount->id, 'content_type' => 'linkedin_post'],
],
])
->assertUnprocessable()
->assertJsonValidationErrors(['media']);
expect(Post::where('content', 'Bad type post')->exists())->toBeFalse();
expect(Media::where('mediable_id', $this->workspace->id)->count())->toBe(0);
});
it('keeps an already-hosted item and a freshly-hosted url in order', function () {
$this->socialAccount->update(['is_active' => true]);
Http::fake([
'cdn.example.com/external.jpg' => Http::response(
file_get_contents(__DIR__.'/../../fixtures/1x1.png'),
200,
['Content-Type' => 'image/png'],
),
]);
$this->withHeaders(['Authorization' => 'Bearer '.$this->plainToken])
->postJson(route('api.posts.store'), [
'content' => 'Mixed media post',
'media' => [
['id' => 'hosted-1', 'path' => 'assets/already.jpg', 'url' => 'https://cdn.trypost.test/assets/already.jpg', 'type' => 'image'],
['url' => 'https://cdn.example.com/external.jpg'],
],
'platforms' => [
['social_account_id' => $this->socialAccount->id, 'content_type' => 'linkedin_post'],
],
])
->assertCreated();
$media = Post::where('content', 'Mixed media post')->firstOrFail()->media;
expect($media)->toHaveCount(2)
->and(data_get($media, '0.path'))->toBe('assets/already.jpg')
->and(data_get($media, '1.url'))->not->toContain('cdn.example.com')
->and(data_get($media, '1.path'))->not->toBeNull();
// Only the external URL is hosted; the passed-through item creates no new row.
expect(Media::where('mediable_id', $this->workspace->id)->count())->toBe(1);
});
it('passes already-hosted media through on create without downloading', function () {
$this->socialAccount->update(['is_active' => true]);
Http::preventStrayRequests();