domain = 'product-test-' . Str::random(8) . '.erp.local'; $tenantId = 'test_tenant_p_' . Str::random(8); // 建立租戶 tenancy()->central(function () use ($tenantId) { $this->tenant = Tenant::create([ 'id' => $tenantId, 'name' => 'Product Test Tenant', ]); $this->tenant->domains()->create(['domain' => $this->domain]); }); // 初始化租戶並遷移 tenancy()->initialize($this->tenant); \Artisan::call('tenants:migrate'); // 建立測試使用者與分類 $this->user = User::factory()->create(['name' => 'Test Admin']); Category::create(['name' => '測試分類', 'code' => 'TEST-CAT']); tenancy()->end(); } protected function tearDown(): void { if ($this->tenant) { $this->tenant->delete(); } parent::tearDown(); } /** * 測試產品同步新增功能 */ public function test_product_sync_can_create_new_product() { \Laravel\Sanctum\Sanctum::actingAs($this->user, ['*']); $payload = [ 'external_pos_id' => 'POS-NEW-999', 'name' => '全新同步商品', 'price' => 299, 'barcode' => '1234567890123', 'category' => '測試分類', 'cost_price' => 150 ]; $response = $this->withHeaders([ 'X-Tenant-Domain' => $this->domain, 'Accept' => 'application/json', ])->postJson('/api/v1/integration/products/upsert', $payload); $response->assertStatus(200) ->assertJsonPath('message', 'Product synced successfully'); // 驗證租戶資料庫 tenancy()->initialize($this->tenant); $this->assertDatabaseHas('products', [ 'external_pos_id' => 'POS-NEW-999', 'name' => '全新同步商品', 'price' => 299, ]); tenancy()->end(); } /** * 測試產品同步更新功能 (Upsert) */ public function test_product_sync_can_update_existing_product() { // 先建立一個既有商品 tenancy()->initialize($this->tenant); Product::create([ 'name' => '舊商品名稱', 'code' => 'OLD-CODE', 'external_pos_id' => 'POS-EXIST-001', 'price' => 100, 'category_id' => Category::first()->id, ]); tenancy()->end(); \Laravel\Sanctum\Sanctum::actingAs($this->user, ['*']); $payload = [ 'external_pos_id' => 'POS-EXIST-001', 'name' => '更新後的商品名稱', 'price' => 888, ]; $response = $this->withHeaders([ 'X-Tenant-Domain' => $this->domain, 'Accept' => 'application/json', ])->postJson('/api/v1/integration/products/upsert', $payload); $response->assertStatus(200); tenancy()->initialize($this->tenant); $this->assertDatabaseHas('products', [ 'external_pos_id' => 'POS-EXIST-001', 'name' => '更新後的商品名稱', 'price' => 888, ]); tenancy()->end(); } /** * 測試產品同步驗證失敗 */ public function test_product_sync_validation_fails_without_required_fields() { \Laravel\Sanctum\Sanctum::actingAs($this->user, ['*']); $payload = [ 'external_pos_id' => '', // 缺少此欄位 'name' => '', // 缺少此欄位 ]; $response = $this->withHeaders([ 'X-Tenant-Domain' => $this->domain, 'Accept' => 'application/json', ])->postJson('/api/v1/integration/products/upsert', $payload); $response->assertStatus(422) ->assertJsonValidationErrors(['external_pos_id', 'name']); } }