400], baseUrl: 'https://api.mts.ru/client-omni-adapter_production/1.0.2', naming: 'MTSM_Test', connectTo: null, ); } function mts_message(string $sender = 'liderra.ru'): SmsOutgoing { return new SmsOutgoing( phone: '79990000001', body: 'Здравствуйте!', senderName: $sender, operator: 'МТС', segments: 1, ); } function mts_ok(int $messageId = 44444634): array { return [ 'code' => 0, 'description' => '', 'data' => ['submitResults' => [['msid' => '79990000001', 'messageID' => $messageId, 'code' => 'OK']]], ]; } /** Отправить и вернуть пойманное SmsSendException; если исключения не было — провалить тест. */ function mts_thrown(): SmsSendException { try { mts_provider()->send(mts_message()); } catch (SmsSendException $e) { return $e; } throw new RuntimeException('ожидалось SmsSendException, но отправка прошла без ошибки'); } it('обслуживает только МТС', function () { expect(mts_provider()->servesOperators())->toBe(['mts']) ->and(mts_provider()->key())->toBe('mts'); }); it('успешная отправка возвращает messageID и цену', function () { Http::fake(['api.mts.ru/*' => Http::response(mts_ok(), 200)]); $result = mts_provider()->send(mts_message()); expect($result->providerMessageId)->toBe('44444634') ->and($result->costKopecks)->toBe(400); Http::assertSent(function ($request) { return str_contains($request->url(), 'mcom/messageManagement/messages') && $request['submits'][0]['msid'] === '79990000001' && $request['submits'][0]['message'] === 'Здравствуйте!' && $request['naming'] === 'liderra.ru' && $request->hasHeader('Authorization', 'Bearer token-xxx'); }); }); it('имя отправителя из сообщения важнее дефолтного канала', function () { Http::fake(['api.mts.ru/*' => Http::response(mts_ok(), 200)]); mts_provider()->send(mts_message('CustomName')); Http::assertSent(fn ($request) => $request['naming'] === 'CustomName'); }); it('пустое имя в сообщении → берём дефолтное имя канала', function () { Http::fake(['api.mts.ru/*' => Http::response(mts_ok(), 200)]); mts_provider()->send(mts_message('')); Http::assertSent(fn ($request) => $request['naming'] === 'MTSM_Test'); }); it('прикладной code != 0 — terminal', function () { Http::fake(['api.mts.ru/*' => Http::response(['code' => 1005, 'description' => 'naming not found'], 200)]); expect(mts_thrown()->terminal)->toBeTrue(); }); it('submitResult code != OK — terminal', function () { Http::fake(['api.mts.ru/*' => Http::response([ 'code' => 0, 'data' => ['submitResults' => [['msid' => '79990000001', 'code' => 'REJECTED']]], ], 200)]); expect(mts_thrown()->terminal)->toBeTrue(); }); it('HTTP 4xx — terminal', function () { Http::fake(['api.mts.ru/*' => Http::response('', 400)]); expect(mts_thrown()->terminal)->toBeTrue(); }); it('HTTP 5xx — не terminal', function () { Http::fake(['api.mts.ru/*' => Http::response('', 503)]); expect(mts_thrown()->terminal)->toBeFalse(); });