user->attachPermission(Permission::where('name', 'read-admin-panel')->firstOrFail()); $repository = Mockery::mock(SupplierManagementMirrorRepository::class); $repository->shouldReceive('ready')->andReturn($ready); $repository->shouldReceive('state')->andReturn(null); $this->app->instance(SupplierManagementMirrorRepository::class, $repository); $this->freeShipping = Mockery::mock(SupplierFreeShippingStore::class); $this->freeShipping->shouldReceive('decorateRows')->andReturnUsing( static fn (array $rows): array => $rows, ); $this->freeShipping->shouldReceive('decorateRow')->andReturnUsing( static fn (object $row): object => $row, ); $this->app->instance(SupplierFreeShippingStore::class, $this->freeShipping); return $repository; } private function url(array $query = []): string { return route('business.pages.show', ['section' => 'supplier-payables', 'page' => 'supplier-management', ...$query]); } public function test_initial_sync_pending_is_explicit_and_export_is_unavailable(): void { $repository = $this->repository(false); $repository->shouldNotReceive('paginate'); $this->loginAs()->get($this->url())->assertOk()->assertSeeText('供应商管理')->assertSeeText('供应商资料尚未完成首次同步'); $this->withExceptionHandling()->get(route('business.supplier-management.export'))->assertStatus(503); } public function test_filters_and_selected_supplier_details_render_without_full_page_navigation(): void { $repository = $this->repository(true); $row = (object) ['Id' => 3, 'scmcode' => '001', 'scmname' => '测试供应商', 'coopersgn' => 1, 'region' => '苏北', 'sindou' => '双日', 'capacity' => '120', SupplierFreeShippingStore::FIELD => true]; $repository->shouldReceive('paginate')->once()->with(['supplier_name' => '测试', 'buyer' => '', 'cooperation_status' => '1'], 1, 20) ->andReturn(['rows' => [$row], 'total' => 1]); $repository->shouldReceive('details')->once()->with($row, 'contacts', 1, 20) ->andReturn(['rows' => [(object) ['linker' => '测试联系人']], 'total' => 1, 'ready' => true, 'message' => null]); $this->loginAs()->get($this->url(['supplier_name' => ' 测试 ', 'cooperation_status' => '1', 'supplier_id' => 3, 'detail_tab' => 'contacts'])) ->assertOk()->assertSeeText('测试供应商')->assertSeeText('测试联系人')->assertSee('data-caiwu-replay', false)->assertSeeText('打款信息') ->assertSeeText('工厂产能')->assertSeeText('叫货周期')->assertSeeText('赔付终止日期') ->assertSeeText('苏北')->assertSeeText('双日')->assertSeeText('120') ->assertSeeText('是否包邮厂家')->assertSeeText('包邮') ->assertSee('data-supplier-free-shipping', false) ->assertSee('>-', false) ->assertSee(route('business.supplier-management.free-shipping.template'), false); } public function test_detail_failure_keeps_the_supplier_list_visible(): void { $repository = $this->repository(true); $row = (object) ['Id' => 3, 'scmcode' => '001', 'scmname' => '测试供应商', 'coopersgn' => null]; $repository->shouldReceive('paginate')->andReturn(['rows' => [$row], 'total' => 1]); $repository->shouldReceive('details')->andThrow(new \RuntimeException('test detail unavailable')); $this->loginAs()->get($this->url(['supplier_id' => 3]))->assertOk()->assertSeeText('测试供应商')->assertSeeText('该详情资料暂时无法读取'); } public function test_export_uses_all_filtered_rows_and_neutralizes_formula_text(): void { $repository = $this->repository(true); $repository->shouldReceive('exportRows')->once()->with(['supplier_name' => '测试', 'buyer' => '', 'cooperation_status' => '']) ->andReturnUsing(function (): \Generator { for ($id = 1; $id <= 23; $id++) yield (object) ['scmcode' => '123456789012345678', 'scmname' => '=SUM(1,2)', 'coopersgn' => 1]; }); $response = $this->loginAs()->get(route('business.supplier-management.export', ['supplier_name' => '测试', 'page' => 2]))->assertOk(); $content = $response->streamedContent(); $this->assertStringStartsWith("\xEF\xBB\xBF", $content); $this->assertStringStartsWith( "数据来源,是否合作,供应商代码,供应商名称,是否包邮厂家,供应商类型", ltrim($content, "\xEF\xBB\xBF"), ); $this->assertSame(23, substr_count($content, "'=SUM(1,2)")); $this->assertStringContainsString("'123456789012345678", $content); } public function test_free_shipping_flag_can_be_edited_inline(): void { $repository = $this->repository(true); $supplier = (object) ['Id' => 9, 'scmcode' => 'N901', 'scmname' => '一泰']; $repository->shouldReceive('supplierById')->once()->with(9)->andReturn($supplier); $this->freeShipping->shouldReceive('save')->once() ->with(9, true, Mockery::type('int'), Mockery::type('int'), 'manual') ->andReturn(['created' => 1, 'updated' => 0]); $this->loginAs()->patchJson( route('business.supplier-management.free-shipping.update', ['supplier' => 9]), ['value' => '包邮'], )->assertOk()->assertJson([ 'ok' => true, 'value' => '包邮', 'display' => '包邮', ]); } public function test_free_shipping_import_matches_supplier_codes_and_saves_blank_as_false(): void { $repository = $this->repository(true); $suppliers = [ (object) ['Id' => 9, 'scmcode' => 'N901', 'scmname' => '一泰'], (object) ['Id' => 11, 'scmcode' => 'Y411', 'scmname' => '七彩'], ]; $repository->shouldReceive('suppliersByCodes')->once()->with(['N901', 'Y411'])->andReturn($suppliers); $workbook = Mockery::mock(SupplierFreeShippingWorkbook::class); $workbook->shouldReceive('read')->once()->andReturn(['N901' => true, 'Y411' => false]); $this->app->instance(SupplierFreeShippingWorkbook::class, $workbook); $this->freeShipping->shouldReceive('saveMany')->once() ->with([9 => true, 11 => false], Mockery::type('int'), Mockery::type('int'), 'import') ->andReturn(['created' => 2, 'updated' => 0]); $this->loginAs()->post(route('business.supplier-management.free-shipping.import'), [ 'import' => UploadedFile::fake()->create('free-shipping.xlsx', 10, 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'), ])->assertRedirect() ->assertSessionHas('supplier_management_message', '导入完成:新增 2 家供应商维护记录,更新 0 家供应商维护记录。'); } public function test_free_shipping_template_is_downloadable(): void { $this->repository(true); $response = $this->loginAs()->get(route('business.supplier-management.free-shipping.template'))->assertOk(); $this->assertStringStartsWith('PK', $response->streamedContent()); } public function test_unauthenticated_export_requires_login(): void { $this->withExceptionHandling()->get(route('business.supplier-management.export', ['company_id' => $this->company->id]))->assertRedirect(); } }