300], 'https://api.mts.test/v1'); } /** * Ответ МТС на вопрос о судьбе — ровно той формы, что пришла живьём. * * @param array> $statuses * @return array */ function mtsDeliveryBody(string $messageId, array $statuses): array { return ['code' => 0, 'data' => [['messageID' => $messageId, 'statuses' => $statuses]]]; } it('читает доставленное сообщение по живой форме ответа', function () { Http::fake(['*' => Http::response(mtsDeliveryBody('44747238', [[ 'msid' => '79990000001', 'status' => 'Delivered', 'date' => '2026-07-30T16:31:02', 'userDeliveryDate' => '2026-07-30T16:31:40', 'partCount' => 2, 'isViber' => false, 'trafficPatternType' => 'service', 'cost' => 3.4, ]]))]); $reports = mtsDeliveryProvider()->fetchDelivery(['44747238']); expect($reports)->toHaveCount(1); expect($reports[0]->providerMessageId)->toBe('44747238'); expect($reports[0]->phone)->toBe('79990000001'); expect($reports[0]->state)->toBe(SmsDeliveryState::DELIVERED); expect($reports[0]->deliveredAt?->toDateTimeString())->toBe('2026-07-30 16:31:40'); expect($reports[0]->partCount)->toBe(2); expect($reports[0]->providerCost)->toBe('3.4'); }); it('читает «принял, но не отправил» — тот самый случай живой пробы 30.07', function () { Http::fake(['*' => Http::response(mtsDeliveryBody('44747239', [[ 'msid' => '79990000002', 'status' => 'NotSent', 'date' => '2026-07-30T16:31:02', 'userDeliveryDate' => null, 'partCount' => 1, 'cost' => 0, ]]))]); $reports = mtsDeliveryProvider()->fetchDelivery(['44747239']); expect($reports[0]->state)->toBe(SmsDeliveryState::NOT_SENT); expect($reports[0]->deliveredAt)->toBeNull(); expect($reports[0]->providerCost)->toBe('0'); }); it('читает «везу» и «не довёз» как разные судьбы', function () { Http::fake(['*' => Http::response(['code' => 0, 'data' => [ ['messageID' => '1', 'statuses' => [['msid' => '79990000003', 'status' => 'Sending']]], ['messageID' => '2', 'statuses' => [['msid' => '79990000004', 'status' => 'NotDelivered']]], ]])]); $reports = mtsDeliveryProvider()->fetchDelivery(['1', '2']); expect($reports[0]->state)->toBe(SmsDeliveryState::SENDING); expect($reports[1]->state)->toBe(SmsDeliveryState::NOT_DELIVERED); }); it('незнакомое слово оператора не угадывает, а отдаёт пустую судьбу и само слово', function () { Http::fake(['*' => Http::response(mtsDeliveryBody('1', [[ 'msid' => '79990000005', 'status' => 'СовершенноНовоеСлово', 'partCount' => 1, ]]))]); $reports = mtsDeliveryProvider()->fetchDelivery(['1']); expect($reports[0]->state)->toBeNull(); expect($reports[0]->rawState)->toBe('СовершенноНовоеСлово'); }); it('спрашивает номера сообщений одной строкой через запятую', function () { Http::fake(['*' => Http::response(['code' => 0, 'data' => []])]); mtsDeliveryProvider()->fetchDelivery(['1', '2', '3']); Http::assertSent(fn ($request) => str_contains(urldecode($request->url()), 'messageIDs=1,2,3')); }); it('пустой список никого не спрашивает вовсе', function () { Http::fake(['*' => Http::response(['code' => 0, 'data' => []])]); expect(mtsDeliveryProvider()->fetchDelivery([]))->toBe([]); Http::assertNothingSent(); }); it('отказ МТС — не окончательный: судьбу всегда можно переспросить позже', function () { Http::fake(['*' => Http::response('', 502)]); try { mtsDeliveryProvider()->fetchDelivery(['1']); $this->fail('ожидали отказ канала'); } catch (SmsSendException $e) { expect($e->terminal)->toBeFalse(); } });