Files
yuan-lab-llm--clawmanager/backend/internal/services/skill_import_test.go
T
heranran 71c7672545 feat: Skill Hub hardening with session usage tracking and egress governance (#163)
* feat(skill-hub): add Skill Hub catalog, publish flow, and lite materialize pipeline

Introduce Skill Hub for browsing, importing, publishing, and installing skills, with lite instance package materialization and runtime sync support.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(skill-hub): remove token-governance hooks from Skill Hub PR

Strip validateManagedRuntimeEnvironmentOverrides, network lock policy sync,
and egress proxy audit wiring that belong to the upcoming token-usage work,
so the Skill Hub branch compiles independently.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(skill-hub): update migration number in materialize docs

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(skill-hub): make RuntimeAgentClient test stub and hub tests compile-safe

Add ResyncInstanceSkills to the runtime pool handler fake client, and harden
skill hub payload helpers/tests against nil storage/instance repos so go test passes.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat: add Skill Hub hardening with session usage tracking and egress governance

Unify Skill Hub runtime sync improvements with session-token observability,
egress network policy, and admin/instance usage reporting for reopenable PR.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix(skill-hub): repair CI tests and nested skill install

* fix(ci): restore release deployment configuration

---------

Co-authored-by: heshengran <heshengran@ieisystem.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-17 12:37:01 +08:00

76 lines
2.6 KiB
Go

package services
import (
"testing"
"clawreef/internal/models"
)
func TestPreviewImportDirectoryNone(t *testing.T) {
svc := &skillService{repo: &skillRepoStub{skills: map[int]*models.Skill{}}}
item, err := svc.previewImportDirectory(1, extractedSkillDirectory{
Name: "weather",
Files: map[string][]byte{"SKILL.md": []byte("# weather")},
})
if err != nil {
t.Fatalf("previewImportDirectory() error = %v", err)
}
if item.ConflictType != skillImportConflictNone {
t.Fatalf("conflict_type = %q, want %q", item.ConflictType, skillImportConflictNone)
}
}
func TestPreviewImportDirectoryUnchanged(t *testing.T) {
versionID := 10
blobID := 20
dir := extractedSkillDirectory{Name: "weather", Files: map[string][]byte{"SKILL.md": []byte("# weather")}}
contentHash := hashDirectory(dir.Files)
stub := &skillRepoStub{
skills: map[int]*models.Skill{
1: {
ID: 1, UserID: 1, SkillKey: "weather", Name: "Weather", Status: skillStatusActive,
SourceType: skillSourceUploaded, CurrentVersionID: &versionID,
},
},
versions: map[int]*models.SkillVersion{versionID: {ID: versionID, SkillID: 1, BlobID: blobID, VersionNo: 2}},
blobs: map[int]*models.SkillBlob{blobID: {ID: blobID, ContentHash: contentHash, ScanStatus: "completed"}},
}
svc := &skillService{repo: stub}
item, err := svc.previewImportDirectory(1, dir)
if err != nil {
t.Fatalf("previewImportDirectory() error = %v", err)
}
if item.ConflictType != skillImportConflictUnchanged {
t.Fatalf("conflict_type = %q, want %q", item.ConflictType, skillImportConflictUnchanged)
}
}
func TestPreviewImportDirectoryContentChanged(t *testing.T) {
versionID := 10
blobID := 20
stub := &skillRepoStub{
skills: map[int]*models.Skill{
1: {
ID: 1, UserID: 1, SkillKey: "weather", Name: "Weather", Status: skillStatusActive,
SourceType: skillSourceUploaded, CurrentVersionID: &versionID,
},
},
versions: map[int]*models.SkillVersion{versionID: {ID: versionID, SkillID: 1, BlobID: blobID, VersionNo: 2}},
blobs: map[int]*models.SkillBlob{blobID: {ID: blobID, ContentHash: "old-hash", ScanStatus: "completed"}},
}
svc := &skillService{repo: stub}
item, err := svc.previewImportDirectory(1, extractedSkillDirectory{
Name: "weather",
Files: map[string][]byte{"SKILL.md": []byte("# changed")},
})
if err != nil {
t.Fatalf("previewImportDirectory() error = %v", err)
}
if item.ConflictType != skillImportConflictContentChanged {
t.Fatalf("conflict_type = %q, want %q", item.ConflictType, skillImportConflictContentChanged)
}
if item.SuggestedSkillKey == nil || *item.SuggestedSkillKey != "weather-2" {
t.Fatalf("suggested skill key = %v, want weather-2", item.SuggestedSkillKey)
}
}