mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-05-15 00:32:47 -04:00
app picker: extend App Picker to integrate with mime overrides
- Adds "DMS Opener" as an option (dms-open.desktop) - Add mime type GO utils - Add rememberance to App Picker modal
This commit is contained in:
@@ -0,0 +1,233 @@
|
||||
package desktop
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func setupFakeXDG(t *testing.T) (configHome, dataHome string) {
|
||||
t.Helper()
|
||||
tmp := t.TempDir()
|
||||
configHome = filepath.Join(tmp, "config")
|
||||
dataHome = filepath.Join(tmp, "data")
|
||||
if err := os.MkdirAll(filepath.Join(dataHome, "applications"), 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.MkdirAll(configHome, 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
t.Setenv("XDG_CONFIG_HOME", configHome)
|
||||
t.Setenv("XDG_DATA_HOME", dataHome)
|
||||
t.Setenv("XDG_DATA_DIRS", dataHome)
|
||||
t.Setenv("XDG_CONFIG_DIRS", configHome)
|
||||
InvalidateCache()
|
||||
|
||||
mimeCacheReloadMu.Lock()
|
||||
mimeCacheMap = nil
|
||||
mimeCacheReloadMu.Unlock()
|
||||
aliasReloadMu.Lock()
|
||||
aliasMap = nil
|
||||
subclassMap = nil
|
||||
aliasReloadMu.Unlock()
|
||||
|
||||
return configHome, dataHome
|
||||
}
|
||||
|
||||
func writeFile(t *testing.T, path, content string) {
|
||||
t.Helper()
|
||||
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseDesktopEntry(t *testing.T) {
|
||||
_, dataHome := setupFakeXDG(t)
|
||||
writeFile(t, filepath.Join(dataHome, "applications", "test.desktop"), `[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Test
|
||||
Exec=test %f
|
||||
Icon=test
|
||||
MimeType=application/pdf;image/png;
|
||||
Categories=Office;Viewer;
|
||||
NoDisplay=false
|
||||
`)
|
||||
|
||||
entry := EntryByID("test.desktop")
|
||||
if entry == nil {
|
||||
t.Fatal("entry not found")
|
||||
}
|
||||
if entry.Name != "Test" {
|
||||
t.Errorf("Name = %q", entry.Name)
|
||||
}
|
||||
if len(entry.MimeTypes) != 2 || entry.MimeTypes[0] != "application/pdf" {
|
||||
t.Errorf("MimeTypes = %v", entry.MimeTypes)
|
||||
}
|
||||
if len(entry.Categories) != 2 || entry.Categories[1] != "Viewer" {
|
||||
t.Errorf("Categories = %v", entry.Categories)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetGetDefault(t *testing.T) {
|
||||
configHome, dataHome := setupFakeXDG(t)
|
||||
writeFile(t, filepath.Join(dataHome, "applications", "foo.desktop"), `[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Foo
|
||||
MimeType=application/pdf;
|
||||
`)
|
||||
writeFile(t, filepath.Join(dataHome, "applications", "bar.desktop"), `[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Bar
|
||||
MimeType=application/pdf;
|
||||
`)
|
||||
|
||||
if err := SetDefault("application/pdf", "bar.desktop"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if got := GetDefault("application/pdf"); got != "bar.desktop" {
|
||||
t.Errorf("GetDefault = %q want bar.desktop", got)
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(filepath.Join(configHome, "mimeapps.list"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !contains(string(data), "application/pdf=bar.desktop") {
|
||||
t.Errorf("mimeapps.list missing default:\n%s", string(data))
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultBypassesMimeSupportCheck(t *testing.T) {
|
||||
configHome, dataHome := setupFakeXDG(t)
|
||||
writeFile(t, filepath.Join(dataHome, "applications", "dms-open.desktop"), `[Desktop Entry]
|
||||
Type=Application
|
||||
Name=DMS
|
||||
MimeType=x-scheme-handler/http;
|
||||
`)
|
||||
|
||||
if err := SetDefault("application/pdf", "dms-open.desktop"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if got := GetDefault("application/pdf"); got != "dms-open.desktop" {
|
||||
t.Errorf("GetDefault = %q, want dms-open.desktop (native impl must not enforce MimeType= check)", got)
|
||||
}
|
||||
|
||||
data, _ := os.ReadFile(filepath.Join(configHome, "mimeapps.list"))
|
||||
if !contains(string(data), "application/pdf=dms-open.desktop") {
|
||||
t.Errorf("mimeapps.list missing override:\n%s", string(data))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAliasResolution(t *testing.T) {
|
||||
_, dataHome := setupFakeXDG(t)
|
||||
writeFile(t, filepath.Join(dataHome, "mime", "aliases"), "text/javascript application/javascript\n")
|
||||
writeFile(t, filepath.Join(dataHome, "applications", "editor.desktop"), `[Desktop Entry]
|
||||
Type=Application
|
||||
Name=Editor
|
||||
MimeType=application/javascript;
|
||||
`)
|
||||
writeFile(t, filepath.Join(dataHome, "applications", "mimeinfo.cache"), `[MIME Cache]
|
||||
application/javascript=editor.desktop;
|
||||
`)
|
||||
|
||||
if got := GetDefault("text/javascript"); got != "editor.desktop" {
|
||||
t.Errorf("GetDefault(text/javascript) = %q want editor.desktop (alias resolution)", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultsBatch(t *testing.T) {
|
||||
configHome, dataHome := setupFakeXDG(t)
|
||||
writeFile(t, filepath.Join(dataHome, "applications", "dms-open.desktop"), `[Desktop Entry]
|
||||
Type=Application
|
||||
Name=DMS
|
||||
MimeType=x-scheme-handler/http;
|
||||
`)
|
||||
|
||||
mimes := []string{
|
||||
"text/plain", "text/x-csrc", "text/x-python",
|
||||
"text/x-shellscript", "application/json",
|
||||
}
|
||||
if err := SetDefaults(mimes, "dms-open.desktop"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(filepath.Join(configHome, "mimeapps.list"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, m := range mimes {
|
||||
if !contains(string(data), m+"=dms-open.desktop") {
|
||||
t.Errorf("missing %s default in mimeapps.list:\n%s", m, string(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestConcurrentSetDefaultNoCorruption(t *testing.T) {
|
||||
configHome, dataHome := setupFakeXDG(t)
|
||||
writeFile(t, filepath.Join(dataHome, "applications", "app.desktop"), `[Desktop Entry]
|
||||
Type=Application
|
||||
Name=App
|
||||
`)
|
||||
|
||||
mimes := []string{
|
||||
"a/1", "a/2", "a/3", "a/4", "a/5", "a/6", "a/7",
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for _, m := range mimes {
|
||||
wg.Add(1)
|
||||
go func(m string) {
|
||||
defer wg.Done()
|
||||
if err := SetDefault(m, "app.desktop"); err != nil {
|
||||
t.Errorf("SetDefault(%s) failed: %v", m, err)
|
||||
}
|
||||
}(m)
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
data, err := os.ReadFile(filepath.Join(configHome, "mimeapps.list"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, m := range mimes {
|
||||
if !contains(string(data), m+"=app.desktop") {
|
||||
t.Errorf("lost write for %s — concurrent writes corrupted file:\n%s", m, string(data))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMimeCacheOrdering(t *testing.T) {
|
||||
_, dataHome := setupFakeXDG(t)
|
||||
writeFile(t, filepath.Join(dataHome, "applications", "a.desktop"), `[Desktop Entry]
|
||||
Type=Application
|
||||
Name=A
|
||||
MimeType=image/png;
|
||||
`)
|
||||
writeFile(t, filepath.Join(dataHome, "applications", "b.desktop"), `[Desktop Entry]
|
||||
Type=Application
|
||||
Name=B
|
||||
MimeType=image/png;
|
||||
`)
|
||||
writeFile(t, filepath.Join(dataHome, "applications", "mimeinfo.cache"), `[MIME Cache]
|
||||
image/png=b.desktop;a.desktop;
|
||||
`)
|
||||
|
||||
if got := GetDefault("image/png"); got != "b.desktop" {
|
||||
t.Errorf("GetDefault should follow mimeinfo.cache order: got %q want b.desktop", got)
|
||||
}
|
||||
}
|
||||
|
||||
func contains(haystack, needle string) bool {
|
||||
for i := 0; i+len(needle) <= len(haystack); i++ {
|
||||
if haystack[i:i+len(needle)] == needle {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user