124 lines
4.8 KiB
Go
124 lines
4.8 KiB
Go
package collector
|
||
|
||
import (
|
||
"os"
|
||
"path/filepath"
|
||
"strings"
|
||
"testing"
|
||
"time"
|
||
)
|
||
|
||
// testOrigin=測試用的三件式(機器/庫/庫內路徑)。
|
||
// 內容不重要,重要的是**每個呼叫端都必須交出它**——`inkstone/Arcrun#167` 的教訓是
|
||
// 「出處寫的是什麼」不能靠預設值,得由知道自己在哪一台、哪個庫的那一端說出來。
|
||
func testOrigin() SourceOrigin {
|
||
return SourceOrigin{MachineLabel: "test@Machine", Library: "test-lib", LibraryPath: "測試文件.md"}
|
||
}
|
||
|
||
// wsOrigin=wikishape 測試用:庫名/機器固定,庫內路徑跟著受測的 relPath 走
|
||
//(子資料夾的檔要驗「資料夾沒被弄丟」,所以這一格不能寫死)。
|
||
func wsOrigin(relPath string) SourceOrigin {
|
||
return SourceOrigin{MachineLabel: "test@Machine", Library: "test-lib", LibraryPath: relPath}
|
||
}
|
||
|
||
// TestSourceOriginNeverEmitsInternalPath 是 `inkstone/Arcrun#167` 的迴歸閘。
|
||
//
|
||
// leo 2026-08-27 用 n8n 實測:問「原文 wiki 的位置在哪裏?」,AI 照著卡片內文答
|
||
// `../小果被AFTEE詐貸.pdf`——**使用者拿著它走不到任何地方**。
|
||
// 這裡把那個形狀鎖死:不管三件式缺哪一格,輸出都不准出現 `../`。
|
||
func TestSourceOriginNeverEmitsInternalPath(t *testing.T) {
|
||
cases := []struct {
|
||
name string
|
||
origin SourceOrigin
|
||
want []string
|
||
}{
|
||
{
|
||
"三件齊全",
|
||
SourceOrigin{MachineLabel: "youlinhsieh@Leo-MBA", Library: "youlinhsieh-test1", LibraryPath: "小果被AFTEE詐貸.pdf"},
|
||
[]string{"youlinhsieh@Leo-MBA › youlinhsieh-test1 › 小果被AFTEE詐貸.pdf", "`youlinhsieh-test1/小果被AFTEE詐貸.pdf`"},
|
||
},
|
||
{
|
||
// 🔴 票上的驗收條件三:子資料夾裡的檔要定位得到。
|
||
// 舊寫法 `../<檔名>` 會把整段資料夾弄丟(實據:inkstoneco 庫的
|
||
// system-dev/wiki/trees/2026-08-17-today.md 出處只剩 `../2026-08-17-today.md`)。
|
||
"子資料夾不准被弄丟",
|
||
SourceOrigin{MachineLabel: "youlinhsieh@Leo-MBA", Library: "inkstoneco", LibraryPath: "system-dev/wiki/trees/2026-08-17-today.md"},
|
||
[]string{"inkstoneco › system-dev/wiki/trees/2026-08-17-today.md", "`inkstoneco/system-dev/wiki/trees/2026-08-17-today.md`"},
|
||
},
|
||
{
|
||
"機器未知也要誠實,不得退回相對路徑",
|
||
SourceOrigin{Library: "kb", LibraryPath: "a/b.md"},
|
||
[]string{"機器(未知) › kb › a/b.md"},
|
||
},
|
||
{
|
||
"庫未知",
|
||
SourceOrigin{MachineLabel: "m", LibraryPath: "a/b.md"},
|
||
[]string{"m › 知識庫(未知) › a/b.md", "`a/b.md`"},
|
||
},
|
||
{
|
||
"路徑未知",
|
||
SourceOrigin{MachineLabel: "m", Library: "kb"},
|
||
[]string{"m › kb › 庫內路徑(未知)"},
|
||
},
|
||
}
|
||
for _, c := range cases {
|
||
t.Run(c.name, func(t *testing.T) {
|
||
var b strings.Builder
|
||
renderSourceLine(&b, c.origin, "某卡")
|
||
got := b.String()
|
||
if strings.Contains(got, "../") {
|
||
t.Fatalf("出處帶內部相對路徑:\n%s", got)
|
||
}
|
||
for _, w := range c.want {
|
||
if !strings.Contains(got, w) {
|
||
t.Fatalf("出處少了「%s」:\n%s", w, got)
|
||
}
|
||
}
|
||
// 人話那行不准變成三元組(`## 關聯` 的解析只收含兩個分隔符的行)。
|
||
human := strings.Split(strings.TrimSpace(got), "\n")[1]
|
||
if strings.Contains(human, triSep) {
|
||
t.Fatalf("人話位置那行含三元組分隔符,會被當成一條邊:%s", human)
|
||
}
|
||
})
|
||
}
|
||
}
|
||
|
||
// TestBuildWikiDocSourceLocatesSubfolderDoc 走完整落地路徑(不是只測 renderer):
|
||
// 子資料夾裡的原稿,產出的文件卡與概念卡都要寫得出「庫內完整路徑」。
|
||
func TestBuildWikiDocSourceLocatesSubfolderDoc(t *testing.T) {
|
||
root := t.TempDir()
|
||
rel := "專案/會議/週會.md"
|
||
if err := os.MkdirAll(filepath.Join(root, "專案", "會議"), 0o755); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
src := "# 週會\n\n甲和乙討論了進度。\n"
|
||
if err := os.WriteFile(filepath.Join(root, filepath.FromSlash(rel)), []byte(src), 0o644); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
ex := &DocExtract{
|
||
Gloss: "週會記錄", Summary: "甲乙討論進度", Points: []string{"討論了進度"},
|
||
Concepts: []WikiConcept{{Name: "進度", Gloss: "專案進度", Summary: "專案進度的討論"}},
|
||
}
|
||
origin := SourceOrigin{MachineLabel: "youlinhsieh@Leo-MBA", Library: "inkstoneco", LibraryPath: rel}
|
||
cards, err := BuildWikiDoc(root, rel, src, ex, origin, time.Date(2026, 8, 27, 0, 0, 0, 0, time.UTC))
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
if len(cards) == 0 {
|
||
t.Fatal("沒產出卡")
|
||
}
|
||
for _, c := range cards {
|
||
body, rerr := os.ReadFile(filepath.Join(root, filepath.FromSlash(c)))
|
||
if rerr != nil {
|
||
t.Fatal(rerr)
|
||
}
|
||
card := string(body)
|
||
if strings.Contains(card, "../") {
|
||
t.Fatalf("%s 仍帶 `../`:\n%s", c, card)
|
||
}
|
||
if !strings.Contains(card, "inkstoneco › 專案/會議/週會.md") {
|
||
t.Fatalf("%s 的出處定位不到子資料夾:\n%s", c, card)
|
||
}
|
||
}
|
||
}
|