TestUpdateCommand_RealSkillsSyncRewritesState is a live integration test that verifies "lark-cli update" correctly triggers skills sync and rewrites the state file. It calls the real npx skills CLI, so the test is skipped when npx or the skills registry is unavailable (e.g. no network or fork PRs).
(t *testing.T)
| 1379 | // state file. It calls the real npx skills CLI, so the test is skipped when |
| 1380 | // npx or the skills registry is unavailable (e.g. no network or fork PRs). |
| 1381 | func TestUpdateCommand_RealSkillsSyncRewritesState(t *testing.T) { |
| 1382 | // Phase 1: Verify the real npx skills CLI is available; skip otherwise. |
| 1383 | if _, err := exec.LookPath("npx"); err != nil { |
| 1384 | t.Skipf("npx not found in PATH: %v", err) |
| 1385 | } |
| 1386 | ctx, cancel := context.WithTimeout(context.Background(), 45*time.Second) |
| 1387 | defer cancel() |
| 1388 | if err := exec.CommandContext(ctx, "npx", "-y", "skills", "add", "https://open.feishu.cn", "--list").Run(); err != nil { |
| 1389 | t.Skipf("real skills CLI unavailable: %v", err) |
| 1390 | } |
| 1391 | globalOut, err := exec.CommandContext(ctx, "npx", "-y", "skills", "ls", "-g").Output() |
| 1392 | if err != nil { |
| 1393 | t.Skipf("real global skills CLI unavailable: %v", err) |
| 1394 | } |
| 1395 | localSkills := skillscheck.ParseSkillsList(string(globalOut)) |
| 1396 | if err := ctx.Err(); err != nil { |
| 1397 | t.Skipf("real skills CLI availability check timed out: %v", err) |
| 1398 | } |
| 1399 | |
| 1400 | // Phase 2: Seed a previous sync state simulating an upgrade from v1.0.19. |
| 1401 | // lark-doc and lark-mail are recorded as skipped/deleted, meaning the user |
| 1402 | // intentionally removed them while they were still official skills. |
| 1403 | t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir()) |
| 1404 | before := skillscheck.SkillsState{ |
| 1405 | Version: "1.0.19", |
| 1406 | OfficialSkills: []string{"lark-approval", "lark-attendance", "lark-base", "lark-calendar", "lark-contact", "lark-doc", "lark-drive", "lark-event", "lark-im", "lark-mail", "lark-markdown", "lark-minutes", "lark-okr", "lark-openapi-explorer", "lark-shared", "lark-sheets", "lark-skill-maker", "lark-slides", "lark-task", "lark-vc", "lark-vc-agent", "lark-whiteboard", "lark-wiki", "lark-workflow-meeting-summary", "lark-workflow-standup-report"}, |
| 1407 | UpdatedSkills: []string{"lark-approval", "lark-apps", "lark-attendance", "lark-base", "lark-calendar", "lark-contact", "lark-doc", "lark-drive", "lark-event", "lark-im", "lark-mail", "lark-markdown", "lark-minutes", "lark-okr", "lark-openapi-explorer", "lark-shared", "lark-sheets", "lark-skill-maker", "lark-slides", "lark-task", "lark-vc", "lark-vc-agent", "lark-whiteboard", "lark-wiki", "lark-workflow-meeting-summary", "lark-workflow-standup-report"}, |
| 1408 | AddedOfficialSkills: []string{}, |
| 1409 | SkippedDeletedSkills: []string{}, |
| 1410 | UpdatedAt: "2026-05-20T00:00:00Z", |
| 1411 | } |
| 1412 | if err := skillscheck.WriteState(before); err != nil { |
| 1413 | t.Fatal(err) |
| 1414 | } |
| 1415 | state, readable, err := skillscheck.ReadState() |
| 1416 | if err != nil || !readable { |
| 1417 | t.Fatalf("ReadState() before update = (_, %v, %v), want readable", readable, err) |
| 1418 | } |
| 1419 | if state.Version != "1.0.19" { |
| 1420 | t.Fatalf("state.Version before update = %q, want 1.0.19", state.Version) |
| 1421 | } |
| 1422 | |
| 1423 | // Phase 3: Mock version functions so the update command believes it has |
| 1424 | // upgraded from 1.0.19 to 1.0.20, then execute "lark-cli update --json". |
| 1425 | // This triggers SyncSkills which calls the real npx skills add command. |
| 1426 | origFetch := fetchLatest |
| 1427 | origVersion := currentVersion |
| 1428 | t.Cleanup(func() { fetchLatest = origFetch; currentVersion = origVersion }) |
| 1429 | fetchLatest = func() (string, error) { return "1.0.20", nil } |
| 1430 | currentVersion = func() string { return "1.0.20" } |
| 1431 | |
| 1432 | f, stdout, _ := newTestFactory(t) |
| 1433 | cmd := NewCmdUpdate(f) |
| 1434 | cmd.SetArgs([]string{"--json"}) |
| 1435 | if err := cmd.Execute(); err != nil { |
| 1436 | t.Fatalf("lark-cli update --json err = %v, want nil", err) |
| 1437 | } |
| 1438 |
nothing calls this directly
no test coverage detected