9cd0adab22
服務 J-1 / S6「我丟進去的檔案,查得到」的考題 G-6.2: 「要嘛查得到,要嘛**當場被告知這種檔案還不支援**,不准安靜地略過。」 本次只做後半句(轉檔本體另有人閘,等 leo 裁「那段 Go 住哪裡」)。 ## 真實現況比記載更糟 t16 寫的「PDF 被靜默略過」已不成立(t73 的轉檔層把 pdf/docx/xlsx/csv/pptx 都接上了,實測 2 頁中文 PDF 完整抽出)。**真正還在沉默的是別的東西**: 副檔名不在 allowedExt 的檔案在 scan.go 直接 `return nil`—— 不進事件、不進 manifest、不進 status、不進畫面。 使用者丟一份 .doc 進去,從頭到尾一個字都沒有。 實測基線(真檔):丟 .pdf/.md/.doc/.key/.jpg 進資料夾, `collector scan` 只吐出 pdf 與 md 兩個事件,另外三個檔沒留下任何痕跡。 ## 改了什麼 - scan.go:白名單閘不再是死巷。像文件的(.doc/.xls/.ppt/.pages/.key/ .numbers/.odt/.ods/.odp/.rtf/.epub/.wpd/.msg/.eml)逐檔留名; 其餘(圖片/影音/程式碼)只計總數——**避免 Obsidian 附件庫炸出幾百行噪音**。 - 兩個新欄位標 `json:"-"`:collector-trigger schema 是 additionalProperties:false,且 BuildSendablePayload 是淺拷貝 ⇒ 有 tag 就會漏到雲端被擋。這是給本機使用者看的,不上 wire。 - direct.go → status.json → App 首頁一張卡:講檔名與格式(「舊版報告.doc (舊版 Word)」),並告訴他不用重丟、也給替代路(另存成 PDF/.docx)。 - 刻意不進 manifest、不走 CarryForwardActivity:每輪由檔案系統重算, 不製造 t195 那種「跨輪欄位漏 carry 就靜默歸零」的債。 ## 順手修掉一個會讓驗收失效的回歸 同綑的 arcrun-collector 一路自稱 `dev`:退役 fyne 版 (arcrun-tray/build-mac.sh:24,t150/t72)本來就有版本注入, t194 換 Wails 時沒帶過來,Mac 與 Windows 兩邊都掉。 **幹活的是 collector**——它不報版本,就沒人能判斷修復有沒有到使用者手上。 ## 實測 - go test ./... 135 過 0 敗(新增 10 條:scan 5+首頁文案 5) - check-cis / check-render / check-tray 三閘全過;淺色深色都抓過畫面 - 從 **DMG 裡那支** collector 實跑:Info.plist 0.18.6、 collector 回報 v0.18.6 (build 20260806-0101)、 status.json 吐出 skipped_docs=[簡報.key, 舊版報告.doc]、other=1 ⚠️ 未出貨:推 bundles repo 在 GitHub,要 leo 開 D20 閘。 DMG 已備妥 dist/Arcrun-v0.18.6.dmg。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
92 lines
3.1 KiB
Go
92 lines
3.1 KiB
Go
package main
|
||
|
||
// skipped_test.go — 首頁「這些檔案還讀不了」那張卡(G-6.2,2026-08-06)。
|
||
//
|
||
// 這一層驗的不是資料對不對(那在 collector/scan_skipped_test.go),
|
||
// 而是**話有沒有講成人話**:使用者看到的是檔名與該不該動手,
|
||
// 不是 allowedExt、extractor、副檔名白名單這些系統內部詞。
|
||
|
||
import (
|
||
"strings"
|
||
"testing"
|
||
)
|
||
|
||
func TestBuildSkippedNilWhenNothingSkipped(t *testing.T) {
|
||
if got := buildSkipped(syncStatus{}); got != nil {
|
||
t.Fatalf("沒東西被略過時不該生出卡片(會白佔首頁版面):%+v", got)
|
||
}
|
||
}
|
||
|
||
func TestBuildSkippedNamesTheFilesInPlainWords(t *testing.T) {
|
||
u := buildSkipped(syncStatus{
|
||
SkippedDocs: []skippedDoc{
|
||
{Path: "提案/舊版報告.doc", Ext: ".doc"},
|
||
{Path: "簡報.key", Ext: ".key"},
|
||
},
|
||
SkippedDocCount: 2,
|
||
})
|
||
if u == nil {
|
||
t.Fatal("有讀不了的檔卻沒生出卡片=又回到安靜略過")
|
||
}
|
||
if !strings.Contains(u.Title, "2") {
|
||
t.Errorf("標題要講幾個檔,實得 %q", u.Title)
|
||
}
|
||
// 使用者看的是檔名,不是我們的相對路徑。
|
||
if u.Files[0] != "舊版報告.doc(舊版 Word)" {
|
||
t.Errorf("檔名該配上他認得的格式名,實得 %q", u.Files[0])
|
||
}
|
||
if u.Files[1] != "簡報.key(Keynote)" {
|
||
t.Errorf("實得 %q", u.Files[1])
|
||
}
|
||
// 要回答「我現在該做什麼」——答案是不用做什麼,而且要說出替代路。
|
||
for _, want := range []string{"不用重丟", "PDF"} {
|
||
if !strings.Contains(u.Note, want) {
|
||
t.Errorf("說明要包含 %q,實得 %q", want, u.Note)
|
||
}
|
||
}
|
||
// 不准把系統內部詞漏給使用者。
|
||
for _, leak := range []string{"allowedExt", "extractor", "ErrUnsupported", "副檔名"} {
|
||
if strings.Contains(u.Title+u.Note, leak) {
|
||
t.Errorf("不該對使用者講 %q", leak)
|
||
}
|
||
}
|
||
}
|
||
|
||
// 清單有上限,但**總數不能被截掉**——否則使用者以為只有 20 個檔沒進去。
|
||
func TestBuildSkippedShowsRemainderCount(t *testing.T) {
|
||
docs := make([]skippedDoc, 20)
|
||
for i := range docs {
|
||
docs[i] = skippedDoc{Path: "檔.doc", Ext: ".doc"}
|
||
}
|
||
u := buildSkipped(syncStatus{SkippedDocs: docs, SkippedDocCount: 57})
|
||
if u.More != 37 {
|
||
t.Errorf("沒列出來的還有 37 個,實得 %d", u.More)
|
||
}
|
||
if !strings.Contains(u.Title, "57") {
|
||
t.Errorf("標題該講真實總數 57,實得 %q", u.Title)
|
||
}
|
||
}
|
||
|
||
// 整個資料夾都是照片這種情況:不必驚動他,但也不能一個字都不說。
|
||
func TestBuildSkippedOtherOnly(t *testing.T) {
|
||
u := buildSkipped(syncStatus{SkippedOtherCount: 312})
|
||
if u == nil {
|
||
t.Fatal("只有非文件檔時仍要說一句,不能沉默")
|
||
}
|
||
if len(u.Files) != 0 {
|
||
t.Error("非文件檔不逐檔點名(幾百張圖會變成噪音)")
|
||
}
|
||
if !strings.Contains(u.Other, "312") {
|
||
t.Errorf("要講出數量,實得 %q", u.Other)
|
||
}
|
||
}
|
||
|
||
func TestExtLabelFallsBackToRawExt(t *testing.T) {
|
||
if got := extLabel(".xyz"); got != "xyz" {
|
||
t.Errorf("沒對照到的格式原樣顯示,實得 %q", got)
|
||
}
|
||
if got := extLabel(".DOC"); got != "舊版 Word" {
|
||
t.Errorf("大寫副檔名也要認得(Windows 常見),實得 %q", got)
|
||
}
|
||
}
|