66 lines
2.5 KiB
PHP
66 lines
2.5 KiB
PHP
|
|
<?php
|
|||
|
|
|
|||
|
|
declare(strict_types=1);
|
|||
|
|
|
|||
|
|
use App\Models\SystemSetting;
|
|||
|
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
|||
|
|
|
|||
|
|
uses(DatabaseTransactions::class);
|
|||
|
|
|
|||
|
|
beforeEach(function () {
|
|||
|
|
SystemSetting::query()
|
|||
|
|
->where('key', 'supplier_webhook_secret')
|
|||
|
|
->update(['value' => 'test-secret-32chars-aaaaaaaaaaaaaa']);
|
|||
|
|
SystemSetting::query()
|
|||
|
|
->where('key', 'supplier_ip_allowlist')
|
|||
|
|
->update(['value' => '[]']);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('returns 422 JSON when supplier posts invalid payload WITHOUT Accept: application/json header', function () {
|
|||
|
|
// Воспроизводит реальное поведение crm.bp-gr.ru: POST без Accept-JSON.
|
|||
|
|
// До фикса (302→422) Laravel редиректил на / с Set-Cookie, поставщик
|
|||
|
|
// терял тело запроса. После фикса всегда JSON.
|
|||
|
|
$response = $this->call(
|
|||
|
|
'POST',
|
|||
|
|
'/api/webhook/supplier/test-secret-32chars-aaaaaaaaaaaaaa',
|
|||
|
|
[], // params
|
|||
|
|
[], // cookies
|
|||
|
|
[], // files
|
|||
|
|
['HTTP_CONTENT_TYPE' => 'application/x-www-form-urlencoded'], // server: НЕТ Accept JSON
|
|||
|
|
http_build_query([
|
|||
|
|
'vid' => 1,
|
|||
|
|
'project' => 'invalid_no_b_prefix',
|
|||
|
|
'phone' => '79991234567',
|
|||
|
|
'time' => time(),
|
|||
|
|
])
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
$response->assertStatus(422);
|
|||
|
|
expect($response->headers->get('Content-Type'))->toContain('application/json');
|
|||
|
|
$response->assertJsonStructure(['message', 'errors' => ['project']]);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('still works correctly for postJson clients (regression)', function () {
|
|||
|
|
$response = $this->postJson('/api/webhook/supplier/test-secret-32chars-aaaaaaaaaaaaaa', [
|
|||
|
|
'vid' => 1,
|
|||
|
|
'project' => 'invalid_no_b_prefix',
|
|||
|
|
'phone' => '79991234567',
|
|||
|
|
'time' => time(),
|
|||
|
|
]);
|
|||
|
|
|
|||
|
|
$response->assertStatus(422)->assertJsonValidationErrors('project');
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
it('non-webhook routes still use default render (no JSON forced)', function () {
|
|||
|
|
// Регрессионный тест: дефолтный render остальных routes не сломан
|
|||
|
|
// (например /login — должен возвращать redirect, а не JSON).
|
|||
|
|
$response = $this->call(
|
|||
|
|
'POST',
|
|||
|
|
'/login',
|
|||
|
|
['email' => 'bad', 'password' => ''],
|
|||
|
|
[], [], [],
|
|||
|
|
);
|
|||
|
|
// Любой не-200 кроме 422-JSON допустим — главное чтобы наш fix не перехватил
|
|||
|
|
expect($response->headers->get('Content-Type'))->not->toContain('application/json');
|
|||
|
|
});
|