package service import ( "strings" "testing" "github.com/wmms/wmms/internal/model" ) func TestUpdateDescriptionReportsWhatChanged(t *testing.T) { oldMaterial := &model.Material{ID: 7, Name: "轴承", Spec: "6205", Unit: "pcs", Status: "active"} newMaterial := &model.Material{ID: 7, Name: "轴承", Spec: "6205-2RS", Unit: "件", Status: "active"} got := updateDescription(newMaterial, oldMaterial) want := "修改物料:轴承(规格:6205 → 6205-2RS;单位:pcs → 件)" if got != want { t.Fatalf("want %q, got %q", want, got) } } func TestUpdateDescriptionWithoutChangesKeepsNameOnly(t *testing.T) { oldMaterial := &model.Material{ID: 7, Name: "轴承", Status: "active"} newMaterial := &model.Material{ID: 7, Name: "轴承", Status: "active"} got := updateDescription(newMaterial, oldMaterial) // 没有变化时不能留下一个空的括号 if got != "修改物料:轴承" { t.Fatalf("unexpected description: %q", got) } } // 作废和恢复复用的也是 LogUpdate,状态变化必须写进描述, // 否则日志里看不出这是一次作废,只会显示成普通的「修改物料」。 func TestUpdateDescriptionShowsStatusChange(t *testing.T) { oldMaterial := &model.Material{ID: 7, Name: "轴承", Status: "active"} newMaterial := &model.Material{ID: 7, Name: "轴承", Status: "obsolete"} got := updateDescription(newMaterial, oldMaterial) want := "修改物料:轴承(状态:启用 → 作废)" if got != want { t.Fatalf("want %q, got %q", want, got) } } func TestUpdateDescriptionMarksEmptyValues(t *testing.T) { oldMaterial := &model.Material{ID: 7, Name: "轴承", Spec: "", Status: "active"} newMaterial := &model.Material{ID: 7, Name: "轴承", Spec: "6205", Status: "active"} got := updateDescription(newMaterial, oldMaterial) want := "修改物料:轴承(规格:空 → 6205)" if got != want { t.Fatalf("want %q, got %q", want, got) } } // 图片 URL 往往很长,整条塞进描述会把其他变更挤没,所以只报「已更新」。 func TestUpdateDescriptionDoesNotInlineImageURL(t *testing.T) { longURL := "data:image/png;base64," + strings.Repeat("A", 500) oldMaterial := &model.Material{ID: 7, Name: "轴承", Status: "active"} newMaterial := &model.Material{ID: 7, Name: "轴承", Status: "active", MaterialImage: &longURL} got := updateDescription(newMaterial, oldMaterial) if got != "修改物料:轴承(物料图片:已更新)" { t.Fatalf("unexpected description: %q", got) } if strings.Contains(got, "base64") { t.Fatalf("image URL must not be inlined: %q", got) } } func TestUpdateDescriptionWithoutOldMaterialKeepsNameOnly(t *testing.T) { got := updateDescription(&model.Material{ID: 7, Name: "轴承"}, nil) if got != "修改物料:轴承" { t.Fatalf("unexpected description: %q", got) } } // 上层取「修改后」的物料失败时会传 nil 进来,nil 解引用会直接 panic。 func TestLogUpdateSkipsWhenMaterialIsMissing(t *testing.T) { err := NewMaterialLogService().LogUpdate(nil, &model.Material{ID: 7}, "tester") if err != nil { t.Fatalf("nil material should be a no-op, got: %v", err) } }