frappe = $this->createMock(FrappeHttpClient::class); $this->adapter = new FrappeErpAdapter($this->frappe, 'REFURB-HW'); } public function test_create_customer_returns_frappe_id(): void { $this->frappe ->method('post') ->with('/api/resource/Customer', $this->isType('array')) ->willReturn(['data' => ['name' => 'CUST-00001']]); $customer = new Customer('Max Mustermann', 'max@test.de', ['street' => 'Str 1', 'city' => 'Berlin', 'zip' => '10115']); $customer->addPlatformId('ebay', 'buyer123'); $result = $this->adapter->createCustomer($customer); $this->assertSame('CUST-00001', $result); } public function test_create_sales_invoice_submits_and_returns_id(): void { $this->frappe ->expects($this->once()) ->method('post') ->willReturn(['data' => ['name' => 'SINV-00001']]); $this->frappe ->expects($this->once()) ->method('put') ->with($this->stringContains('SINV-00001'), ['docstatus' => 1]) ->willReturn(['data' => ['name' => 'SINV-00001', 'docstatus' => 1]]); $customer = new Customer('Max Mustermann', 'max@test.de', ['street' => 'Str 1', 'city' => 'Berlin', 'zip' => '10115']); $customer->setFrappeCustomerId('CUST-00001'); $order = new Order( new Article(new ArticleType('Laptop'), 'LAP-001', 'INV-001', 1, ArticleCondition::Good), $customer, new Platform('ebay', 'eBay DE'), 'ORDER-001', '299.99', new \DateTimeImmutable('2026-05-13'), ); $result = $this->adapter->createSalesInvoice($order); $this->assertSame('SINV-00001', $result); } public function test_fetch_invoice_pdf_returns_binary(): void { $this->frappe ->method('getContent') ->with($this->stringContains('SINV-00001')) ->willReturn('%PDF-binary-content'); $result = $this->adapter->fetchInvoicePdf('SINV-00001'); $this->assertStringStartsWith('%PDF', $result); } public function test_find_existing_customer_returns_id_when_address_matches(): void { $this->frappe ->expects($this->exactly(2)) ->method('get') ->willReturnOnConsecutiveCalls( ['data' => [['name' => 'CUST-99999']]], ['data' => [['address_line1' => 'Kirchstr. 1', 'city' => 'Karbach', 'pincode' => '56281']]], ); $result = $this->adapter->findExistingCustomer('Simon Kühn', 'Kirchstr. 1', 'Karbach', '56281'); $this->assertSame('CUST-99999', $result); } public function test_find_existing_customer_returns_null_when_address_mismatch(): void { $this->frappe ->expects($this->exactly(2)) ->method('get') ->willReturnOnConsecutiveCalls( ['data' => [['name' => 'CUST-99999']]], ['data' => [['address_line1' => 'Musterstr. 5', 'city' => 'Berlin', 'pincode' => '10115']]], ); $result = $this->adapter->findExistingCustomer('Simon Kühn', 'Kirchstr. 1', 'Karbach', '56281'); $this->assertNull($result); } public function test_find_existing_customer_returns_null_when_not_in_erp(): void { $this->frappe ->expects($this->once()) ->method('get') ->willReturn(['data' => []]); $result = $this->adapter->findExistingCustomer('Nobody', 'Unknown St. 1', 'Nowhere', '00000'); $this->assertNull($result); } public function test_find_simon_and_create_invoice_for_1337(): void { $this->frappe ->expects($this->exactly(2)) ->method('get') ->willReturnOnConsecutiveCalls( ['data' => [['name' => 'CUST-99999']]], ['data' => [['address_line1' => 'Kirchstr. 1', 'city' => 'Karbach', 'pincode' => '56281']]], ); $this->frappe ->expects($this->once()) ->method('post') ->willReturn(['data' => ['name' => 'SINV-13370']]); $this->frappe ->expects($this->once()) ->method('put') ->willReturn(['data' => ['name' => 'SINV-13370', 'docstatus' => 1]]); $frappeId = $this->adapter->findExistingCustomer('Simon Kühn', 'Kirchstr. 1', 'Karbach', '56281'); $this->assertSame('CUST-99999', $frappeId); $simon = new Customer('Simon Kühn', 'simon.kuehn83@gmail.com', [ 'street' => 'Kirchstr. 1', 'city' => 'Karbach', 'zip' => '56281', ]); $simon->setFrappeCustomerId($frappeId); $article = new Article( new ArticleType('Laptop'), 'LAP-THINK-001', 'INV-THINK-001', 1, ArticleCondition::Good, ); $article->setManufacturer('Lenovo'); $article->setModelName('ThinkBook 14 G6 IRL'); $article->setModelNumber('21KG00NQGE'); $article->setEbayTitle('Lenovo ThinkBook 14 G6 IRL — generalüberholt, top Zustand'); $order = new Order( $article, $simon, new Platform('direct', 'Direktverkauf'), 'ORDER-SIMON-1337', '1337.00', new \DateTimeImmutable('2026-05-18'), ); $invoiceId = $this->adapter->createSalesInvoice($order); $this->assertSame('SINV-13370', $invoiceId); } }