getTestInstance($options); self::assertEquals($options['id'], $instance->getId()); } /** * @dataProvider validDataProvider */ public function testGetType(array $options): void { $instance = $this->getTestInstance($options); self::assertEquals($options['type'], $instance->getType()); } /** * @dataProvider validDataProvider */ public function testGetStatus(array $options): void { $instance = $this->getTestInstance($options); if (empty($options['status'])) { self::assertNull($instance->getStatus()); } else { self::assertEquals($options['status'], $instance->getStatus()); } } /** * @dataProvider validDataProvider */ public function testGetTaxSystemCode(array $options): void { $instance = $this->getTestInstance($options); if (empty($options['tax_system_code'])) { self::assertNull($instance->getTaxSystemCode()); } else { self::assertEquals($options['tax_system_code'], $instance->getTaxSystemCode()); } } /** * @dataProvider validDataProvider */ public function testGetReceiptOperationalDetails(array $options): void { $instance = $this->getTestInstance($options); if (empty($options['receipt_operational_details'])) { self::assertNull($instance->getReceiptOperationalDetails()); } else { self::assertEquals($options['receipt_operational_details'], $instance->getReceiptOperationalDetails()->toArray()); } } /** * @dataProvider validDataProvider */ public function testReceiptIndustryDetails(array $options): void { $instance = $this->getTestInstance($options); self::assertCount(count($options['receipt_industry_details']), $instance->getReceiptIndustryDetails()); foreach ($instance->getReceiptIndustryDetails() as $index => $item) { self::assertInstanceOf(IndustryDetails::class, $item); self::assertArrayHasKey($index, $options['receipt_industry_details']); self::assertEquals($options['receipt_industry_details'][$index]['federal_id'], $item->getFederalId()); self::assertEquals($options['receipt_industry_details'][$index]['document_date'], $item->getDocumentDate()->format(IndustryDetails::DOCUMENT_DATE_FORMAT)); self::assertEquals($options['receipt_industry_details'][$index]['document_number'], $item->getDocumentNumber()); self::assertEquals($options['receipt_industry_details'][$index]['value'], $item->getValue()); } } /** * @dataProvider validDataProvider */ public function testGetItems(array $options): void { $instance = $this->getTestInstance($options); self::assertEquals(count($options['items']), count($instance->getItems())); foreach ($instance->getItems() as $index => $item) { self::assertInstanceOf(ReceiptResponseItemInterface::class, $item); self::assertArrayHasKey($index, $options['items']); self::assertEquals($options['items'][$index]['description'], $item->getDescription()); self::assertEquals($options['items'][$index]['amount']['value'], $item->getPrice()->getValue()); self::assertEquals($options['items'][$index]['amount']['currency'], $item->getPrice()->getCurrency()); self::assertEquals($options['items'][$index]['quantity'], $item->getQuantity()); self::assertEquals($options['items'][$index]['vat_code'], $item->getVatCode()); } } public function validDataProvider(): array { date_default_timezone_set('UTC'); $this->valid = true; $receipts = []; for ($i = 0; $i < 10; $i++) { $receipts[] = $this->generateReceipts($this->type, true); } return $receipts; } public function invalidDataProvider(): array { $this->valid = false; $receipts = []; for ($i = 0; $i < 10; $i++) { $receipts[] = $this->generateReceipts($this->type, false); } return $receipts; } public function invalidAllDataProvider(): array { return [ [[new ProductCode()]], [[new Airline()]], [SettlementType::PREPAYMENT], [0], ['test'], [10], ]; } public function invalidBoolDataProvider(): array { return [ [true], [false], ]; } public function invalidBoolNullDataProvider(): array { return [ [new \stdClass()], ]; } public function invalidSettlementsDataProvider(): array { return [ [[[]], EmptyPropertyValueException::class], [Random::str(10), TypeError::class], ]; } public function invalidItemsDataProvider(): array { return [ [[[]], EmptyPropertyValueException::class], [Random::str(10), TypeError::class], ]; } public function invalidFromArray(): array { return [ [ [ 'id' => Random::str(39), 'type' => Random::value(ReceiptType::getEnabledValues()), 'status' => null, 'items' => false, ], ], [ [ 'id' => Random::str(39), 'type' => Random::value(ReceiptType::getEnabledValues()), 'status' => null, 'items' => 1, ], ], [ [ 'id' => Random::str(39), 'type' => Random::value(ReceiptType::getValidValues()), 'status' => null, 'items' => [new ReceiptResponseItem()], 'settlements' => 1, ], ], ]; } /** * @param mixed $options */ abstract protected function getTestInstance(mixed $options): ReceiptResponseInterface; /** * @param mixed $i * @param mixed $options */ abstract protected function addSpecificProperties(mixed $options, mixed $i): array; private function generateReceipts($type, $valid): array { $this->valid = $valid; $return = []; $count = Random::int(1, 10); for ($i = 0; $i < $count; $i++) { $return[] = $this->generateReceipt($type, $i); } return $return; } private function generateReceipt($type, $index): array { $receipt = [ 'id' => Random::str(39), 'type' => $type, 'status' => Random::value(['pending', 'succeeded', 'canceled']), 'fiscal_document_number' => Random::int(4), 'fiscal_storage_number' => Random::int(16), 'fiscal_attribute' => Random::int(10), 'registered_at' => date(YOOKASSA_DATE, Random::int(1000000000, time())), 'fiscal_provider_id' => Random::str(36), 'items' => $this->generateItems(), 'settlements' => $this->generateSettlements(), 'tax_system_code' => Random::int(1, 6), 'send' => true, 'internet' => true, 'timezone' => Random::int(1, 11), 'receipt_industry_details' => [ [ 'federal_id' => Random::value([ '00' . Random::int(1, 9), '0' . Random::int(1, 6) . Random::int(0, 9), '07' . Random::int(0, 3) ]), 'document_date' => date(IndustryDetails::DOCUMENT_DATE_FORMAT), 'document_number' => Random::str(1, IndustryDetails::DOCUMENT_NUMBER_MAX_LENGTH), 'value' => Random::str(1, IndustryDetails::VALUE_MAX_LENGTH), ], ], 'receipt_operational_details' => [ 'operation_id' => Random::int(1, OperationalDetails::OPERATION_ID_MAX_VALUE), 'value' => Random::str(1, OperationalDetails::VALUE_MAX_LENGTH), 'created_at' => date(YOOKASSA_DATE, Random::int(1000000000, time())), ], 'on_behalf_of' => Random::int(6), ]; return $this->addSpecificProperties($receipt, $index); } private function generateItems(): array { $return = []; $count = Random::int(1, 10); for ($i = 0; $i < $count; $i++) { $return[] = $this->generateItem(); } return $return; } private function generateItem(): array { $item = [ 'description' => Random::str(1, 128), 'amount' => [ 'value' => round(Random::float(1.00, 100.00), 2), 'currency' => 'RUB', ], 'quantity' => round(Random::float(0.001, 99.999), 3), 'measure' => Random::value(ReceiptItemMeasure::getValidValues()), 'vat_code' => Random::int(1, 6), 'country_of_origin_code' => Random::value(['RU', 'US', 'CN']), 'customs_declaration_number' => Random::str(1, 32), 'mark_code_info' => [ 'mark_code_raw' => '010460406000590021N4N57RTCBUZTQ\u001d2403054002410161218\u001d1424010191ffd0\u001g92tIAF/YVpU4roQS3M/m4z78yFq0nc/WsSmLeX6QkF/YVWwy5IMYAeiQ91Xa2m/fFSJcOkb2N+uUUtfr4n0mOX0Q==', ], 'mark_mode' => 0, 'payment_subject_industry_details' => [ [ 'federal_id' => '001', 'document_date' => date('Y-m-d', Random::int(100000000, 200000000)), 'document_number' => Random::str(1, IndustryDetails::DOCUMENT_NUMBER_MAX_LENGTH), 'value' => Random::str(1, IndustryDetails::VALUE_MAX_LENGTH), ], ], ]; if (ReceiptItemMeasure::PIECE === $item['measure']) { $item['mark_quantity'] = [ 'numerator' => Random::int(1, 100), 'denominator' => 100, ]; } return $item; } private function generateSettlements(): array { $return = []; $count = Random::int(1, 10); for ($i = 0; $i < $count; $i++) { $return[] = $this->generateSettlement(); } return $return; } private function generateSettlement(): array { return [ 'type' => Random::value(SettlementType::getValidValues()), 'description' => Random::str(1, 128), 'amount' => [ 'value' => round(Random::float(1.00, 100.00), 2), 'currency' => 'RUB', ], 'quantity' => round(Random::float(0.001, 99.999), 3), 'vat_code' => Random::int(1, 6), ]; } /** * Test property "internet" * @dataProvider validInternetDataProvider * @param mixed $value * * @return void * @throws Exception */ public function testInternet(mixed $value): void { $instance = $this->getTestInstance([]); self::assertEmpty($instance->getInternet()); self::assertEmpty($instance->internet); $instance->setInternet($value); self::assertEquals($value, $instance->getInternet()); self::assertEquals($value, $instance->internet); if (!empty($value)) { self::assertNotNull($instance->getInternet()); self::assertNotNull($instance->internet); self::assertIsBool($instance->getInternet()); self::assertIsBool($instance->internet); } } /** * Test invalid property "internet" * @dataProvider invalidInternetDataProvider * @param mixed $value * @param string $exceptionClass * * @return void */ public function testInvalidInternet(mixed $value, string $exceptionClass): void { $instance = $this->getTestInstance([]); $this->expectException($exceptionClass); $instance->setInternet($value); } /** * @return array[] * @throws Exception */ public function validInternetDataProvider(): array { $instance = $this->getTestInstance([]); return $this->getValidDataProviderByType($instance->getValidator()->getRulesByPropName('_internet')); } /** * @return array[] * @throws Exception */ public function invalidInternetDataProvider(): array { $instance = $this->getTestInstance([]); return $this->getInvalidDataProviderByType($instance->getValidator()->getRulesByPropName('_internet')); } /** * Test property "timezone" * @dataProvider validTimezoneDataProvider * @param mixed $value * * @return void * @throws Exception */ public function testTimezone(mixed $value): void { $instance = $this->getTestInstance([]); self::assertEmpty($instance->getTimezone()); self::assertEmpty($instance->timezone); $instance->setTimezone($value); self::assertEquals($value, $instance->getTimezone()); self::assertEquals($value, $instance->timezone); if (!empty($value)) { self::assertNotNull($instance->getTimezone()); self::assertNotNull($instance->timezone); self::assertLessThanOrEqual(11, is_string($instance->getTimezone()) ? mb_strlen($instance->getTimezone()) : $instance->getTimezone()); self::assertLessThanOrEqual(11, is_string($instance->timezone) ? mb_strlen($instance->timezone) : $instance->timezone); self::assertGreaterThanOrEqual(1, is_string($instance->getTimezone()) ? mb_strlen($instance->getTimezone()) : $instance->getTimezone()); self::assertGreaterThanOrEqual(1, is_string($instance->timezone) ? mb_strlen($instance->timezone) : $instance->timezone); self::assertIsNumeric($instance->getTimezone()); self::assertIsNumeric($instance->timezone); } } /** * Test invalid property "timezone" * @dataProvider invalidTimezoneDataProvider * @param mixed $value * @param string $exceptionClass * * @return void */ public function testInvalidTimezone(mixed $value, string $exceptionClass): void { $instance = $this->getTestInstance([]); $this->expectException($exceptionClass); $instance->setTimezone($value); } /** * @return array[] * @throws ReflectionException */ public function validTimezoneDataProvider(): array { $instance = $this->getTestInstance([]); return $this->getValidDataProviderByType($instance->getValidator()->getRulesByPropName('_timezone')); } /** * @return array[] */ public function invalidTimezoneDataProvider(): array { $instance = $this->getTestInstance([]); return $this->getInvalidDataProviderByType($instance->getValidator()->getRulesByPropName('_timezone')); } }