Files
MyGoNavi/internal/app/methods_data_root_i18n_test.go
2026-06-22 15:12:42 +08:00

326 lines
12 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package app
import (
"encoding/json"
"os"
"path/filepath"
"strings"
"testing"
"GoNavi-Wails/internal/appdata"
"GoNavi-Wails/shared/i18n"
)
func methodsDataRootFunctionSource(t *testing.T, source string, signature string) string {
t.Helper()
start := strings.Index(source, signature)
if start < 0 {
t.Fatalf("methods_data_root.go missing function signature %q", signature)
}
rest := source[start+len(signature):]
end := strings.Index(rest, "\nfunc ")
if end < 0 {
return source[start:]
}
return source[start : start+len(signature)+end]
}
func TestMethodsDataRootMessagesUseLocalizedText(t *testing.T) {
sourceBytes, err := os.ReadFile("methods_data_root.go")
if err != nil {
t.Fatalf("read methods_data_root.go: %v", err)
}
source := string(sourceBytes)
checks := map[string]struct {
rawMessages []string
keys []string
}{
"func (a *App) SelectDataRootDirectory": {
rawMessages: []string{
`Title: "选择 GoNavi 数据目录"`,
},
keys: []string{
"app.data_root.backend.dialog.select_directory",
},
},
"func (a *App) ApplyDataRootDirectory": {
rawMessages: []string{
`Message: "数据目录未发生变化"`,
`message := "数据目录已更新,建议重启应用以让 AI 与其他运行态模块完全切换到新目录"`,
`message = "数据已迁移并切换到新目录,建议重启应用以完成全部模块切换"`,
},
keys: []string{
"app.data_root.backend.message.unchanged",
"app.data_root.backend.message.updated_restart",
"app.data_root.backend.message.migrated_restart",
},
},
"func dataRootLocalizeSetActiveRootError": {
rawMessages: nil,
keys: []string{
"app.data_root.backend.error.create_data_directory_failed",
"app.data_root.backend.error.create_bootstrap_directory_failed",
},
},
"func (a *App) OpenDataRootDirectory": {
rawMessages: []string{
`Message: "数据目录不存在或不可访问"`,
`fmt.Sprintf("当前平台暂不支持打开目录:%s", stdRuntime.GOOS)`,
`fmt.Sprintf("打开数据目录失败:%v", err)`,
`Message: "已打开数据目录"`,
},
keys: []string{
"app.data_root.backend.error.directory_unavailable",
"app.data_root.backend.error.open_directory_unsupported",
"app.data_root.backend.error.open_directory_failed",
"app.data_root.backend.message.opened",
},
},
"func migrateDataRootContentsWithText": {
rawMessages: []string{
`fmt.Errorf("数据目录不能为空")`,
`fmt.Errorf("解析源数据目录失败:%w", err)`,
`fmt.Errorf("解析目标数据目录失败:%w", err)`,
`fmt.Errorf("目标数据目录不能位于源目录内部")`,
`fmt.Errorf("创建目标数据目录失败:%w", err)`,
`fmt.Errorf("读取源数据目录失败:%w", err)`,
`fmt.Errorf("读取源数据失败(%s%w", name, err)`,
`fmt.Errorf("迁移目录失败(%s%w", name, err)`,
`fmt.Errorf("迁移文件失败(%s%w", name, err)`,
},
keys: []string{
"app.data_root.backend.error.directory_empty",
"app.data_root.backend.error.resolve_source_failed",
"app.data_root.backend.error.resolve_target_failed",
"app.data_root.backend.error.target_inside_source",
"app.data_root.backend.error.create_target_failed",
"app.data_root.backend.error.read_source_root_failed",
"app.data_root.backend.error.read_source_failed",
"app.data_root.backend.error.migrate_directory_failed",
"app.data_root.backend.error.migrate_file_failed",
},
},
"func rewriteSecurityUpdateBackupPathsWithText": {
rawMessages: []string{
`fmt.Errorf("读取迁移后的安全更新状态失败:%w", err)`,
`fmt.Errorf("写入迁移后的安全更新状态失败:%w", err)`,
`fmt.Errorf("读取迁移后的安全更新备份清单失败:%w", err)`,
`fmt.Errorf("解析迁移后的安全更新备份清单失败:%w", err)`,
`fmt.Errorf("写入迁移后的安全更新备份清单失败:%w", err)`,
`fmt.Errorf("读取迁移后的安全更新结果失败:%w", err)`,
`fmt.Errorf("解析迁移后的安全更新结果失败:%w", err)`,
`fmt.Errorf("写入迁移后的安全更新结果失败:%w", err)`,
},
keys: []string{
"app.data_root.backend.error.read_migrated_security_update_state_failed",
"app.data_root.backend.error.write_migrated_security_update_state_failed",
"app.data_root.backend.error.read_migrated_security_update_manifest_failed",
"app.data_root.backend.error.parse_migrated_security_update_manifest_failed",
"app.data_root.backend.error.write_migrated_security_update_manifest_failed",
"app.data_root.backend.error.read_migrated_security_update_result_failed",
"app.data_root.backend.error.parse_migrated_security_update_result_failed",
"app.data_root.backend.error.write_migrated_security_update_result_failed",
},
},
}
for signature, check := range checks {
body := methodsDataRootFunctionSource(t, source, signature)
for _, raw := range check.rawMessages {
if strings.Contains(body, raw) {
t.Fatalf("%s still contains raw data-root text %q", signature, raw)
}
}
for _, key := range check.keys {
if !strings.Contains(body, key) {
t.Fatalf("%s should reference localized key %q", signature, key)
}
}
}
}
func TestMethodsDataRootCatalogKeysExist(t *testing.T) {
catalogs, err := i18n.LoadCatalogs()
if err != nil {
t.Fatalf("LoadCatalogs() error = %v", err)
}
keys := []string{
"app.data_root.backend.dialog.select_directory",
"app.data_root.backend.error.create_target_failed",
"app.data_root.backend.error.create_bootstrap_directory_failed",
"app.data_root.backend.error.create_data_directory_failed",
"app.data_root.backend.error.directory_empty",
"app.data_root.backend.error.directory_unavailable",
"app.data_root.backend.error.migrate_directory_failed",
"app.data_root.backend.error.migrate_file_failed",
"app.data_root.backend.error.open_directory_failed",
"app.data_root.backend.error.open_directory_unsupported",
"app.data_root.backend.error.read_source_failed",
"app.data_root.backend.error.resolve_source_failed",
"app.data_root.backend.error.resolve_target_failed",
"app.data_root.backend.error.target_inside_source",
"app.data_root.backend.error.read_source_root_failed",
"app.data_root.backend.error.read_migrated_security_update_state_failed",
"app.data_root.backend.error.write_migrated_security_update_state_failed",
"app.data_root.backend.error.read_migrated_security_update_manifest_failed",
"app.data_root.backend.error.parse_migrated_security_update_manifest_failed",
"app.data_root.backend.error.write_migrated_security_update_manifest_failed",
"app.data_root.backend.error.read_migrated_security_update_result_failed",
"app.data_root.backend.error.parse_migrated_security_update_result_failed",
"app.data_root.backend.error.write_migrated_security_update_result_failed",
"app.data_root.backend.message.migrated_restart",
"app.data_root.backend.message.opened",
"app.data_root.backend.message.unchanged",
"app.data_root.backend.message.updated_restart",
}
for _, language := range i18n.SupportedLanguages() {
catalog := catalogs[language]
for _, key := range keys {
if strings.TrimSpace(catalog[key]) == "" {
t.Fatalf("%s catalog missing data-root key %q", language, key)
}
}
}
}
func TestApplyDataRootDirectoryUsesEnglishLocalizedMessageWhenUnchanged(t *testing.T) {
homeDir := t.TempDir()
t.Setenv("HOME", homeDir)
t.Setenv("USERPROFILE", homeDir)
app := NewApp()
app.SetLanguage(string(i18n.LanguageEnUS))
t.Cleanup(func() {
app.SetLanguage(string(i18n.LanguageEnUS))
})
defaultRoot := filepath.Join(homeDir, ".gonavi")
result := app.ApplyDataRootDirectory(defaultRoot, false)
if !result.Success {
t.Fatalf("expected success for unchanged root, got %+v", result)
}
want := app.appText("app.data_root.backend.message.unchanged", nil)
if result.Message != want {
t.Fatalf("expected localized unchanged message %q, got %q", want, result.Message)
}
if strings.Contains(result.Message, "数据目录未发生变化") {
t.Fatalf("expected no raw Chinese unchanged message, got %q", result.Message)
}
}
func TestApplyDataRootDirectoryLocalizesCreateDirectoryFailure(t *testing.T) {
homeDir := t.TempDir()
t.Setenv("HOME", homeDir)
t.Setenv("USERPROFILE", homeDir)
blockingPath := filepath.Join(t.TempDir(), "blocked-root")
if err := os.WriteFile(blockingPath, []byte("blocked"), 0o644); err != nil {
t.Fatalf("write blocking path: %v", err)
}
detailErr := os.MkdirAll(blockingPath, 0o755)
if detailErr == nil {
t.Fatalf("expected MkdirAll(%q) to fail against an existing file", blockingPath)
}
app := NewApp()
app.SetLanguage(string(i18n.LanguageEnUS))
t.Cleanup(func() {
app.SetLanguage(string(i18n.LanguageEnUS))
})
result := app.ApplyDataRootDirectory(blockingPath, false)
if result.Success {
t.Fatalf("expected create-directory failure, got %+v", result)
}
want := app.appText("app.data_root.backend.error.create_data_directory_failed", map[string]any{
"detail": detailErr.Error(),
})
if result.Message != want {
t.Fatalf("expected localized create-directory message %q, got %q", want, result.Message)
}
}
func TestMigrateDataRootContentsUsesEnglishLocalizedValidationMessage(t *testing.T) {
setDefaultAppLanguage(i18n.LanguageEnUS)
err := migrateDataRootContents(" ", filepath.Join(t.TempDir(), "target"))
if err == nil {
t.Fatal("expected migrateDataRootContents to fail for empty source root")
}
want := defaultAppText("app.data_root.backend.error.directory_empty", nil)
if err.Error() != want {
t.Fatalf("expected localized empty-directory message %q, got %q", want, err.Error())
}
}
func TestRewriteSecurityUpdateBackupPathsUsesEnglishLocalizedManifestParseError(t *testing.T) {
setDefaultAppLanguage(i18n.LanguageEnUS)
targetRoot := t.TempDir()
repo := newSecurityUpdateStateRepository(targetRoot)
started, err := repo.StartRound(StartSecurityUpdateRequest{SourceType: SecurityUpdateSourceTypeCurrentAppSavedConfig})
if err != nil {
t.Fatalf("start security update round failed: %v", err)
}
if err := os.WriteFile(repo.manifestPath(started.MigrationID), []byte("{"), 0o644); err != nil {
t.Fatalf("write invalid manifest: %v", err)
}
err = rewriteSecurityUpdateBackupPaths(targetRoot)
if err == nil {
t.Fatal("expected rewriteSecurityUpdateBackupPaths to fail for invalid manifest")
}
var manifest securityUpdateBackupManifest
parseErr := json.Unmarshal([]byte("{"), &manifest)
if parseErr == nil {
t.Fatal("expected invalid manifest json to fail")
}
want := defaultAppText("app.data_root.backend.error.parse_migrated_security_update_manifest_failed", map[string]any{
"detail": parseErr.Error(),
})
if err.Error() != want {
t.Fatalf("expected localized manifest-parse message %q, got %q", want, err.Error())
}
}
func TestApplyDataRootDirectoryLocalizesBootstrapDirectoryFailure(t *testing.T) {
homeDir := t.TempDir()
t.Setenv("HOME", homeDir)
t.Setenv("USERPROFILE", homeDir)
defaultRoot := appdata.DefaultRoot()
if err := os.WriteFile(defaultRoot, []byte("blocked"), 0o644); err != nil {
t.Fatalf("write blocking default root: %v", err)
}
app := NewApp()
app.SetLanguage(string(i18n.LanguageEnUS))
t.Cleanup(func() {
app.SetLanguage(string(i18n.LanguageEnUS))
})
targetRoot := filepath.Join(t.TempDir(), "custom-root")
result := app.ApplyDataRootDirectory(targetRoot, false)
if result.Success {
t.Fatalf("expected bootstrap-directory failure, got %+v", result)
}
detailErr := os.MkdirAll(defaultRoot, 0o755)
if detailErr == nil {
t.Fatalf("expected MkdirAll(%q) to fail against an existing file", defaultRoot)
}
want := app.appText("app.data_root.backend.error.create_bootstrap_directory_failed", map[string]any{
"detail": detailErr.Error(),
})
if result.Message != want {
t.Fatalf("expected localized bootstrap-directory message %q, got %q", want, result.Message)
}
}