package plugins import ( "encoding/json" "testing" "github.com/AvengeMedia/DankMaterialShell/core/internal/mocks/net" coreplugins "github.com/AvengeMedia/DankMaterialShell/core/internal/plugins" "github.com/AvengeMedia/DankMaterialShell/core/internal/server/models" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/mock" ) func TestHandleList(t *testing.T) { conn := net.NewMockConn(t) conn.EXPECT().Write(mock.Anything).Return(0, nil).Maybe() req := models.Request{ ID: 123, Method: "plugins.list", Params: map[string]any{}, } HandleList(conn, req) } func TestHandleListInstalled(t *testing.T) { conn := net.NewMockConn(t) conn.EXPECT().Write(mock.Anything).Return(0, nil).Maybe() req := models.Request{ ID: 123, Method: "plugins.listInstalled", Params: map[string]any{}, } HandleListInstalled(conn, req) } func TestHandleInstallMissingName(t *testing.T) { conn := net.NewMockConn(t) var written []byte conn.EXPECT().Write(mock.Anything).RunAndReturn(func(b []byte) (int, error) { written = b return len(b), nil }).Maybe() req := models.Request{ ID: 123, Method: "plugins.install", Params: map[string]any{}, } HandleInstall(conn, req) var resp models.Response[SuccessResult] err := json.Unmarshal(written, &resp) assert.NoError(t, err) assert.NotEmpty(t, resp.Error) assert.Contains(t, resp.Error, "missing or invalid 'name' parameter") } func TestHandleInstallInvalidName(t *testing.T) { conn := net.NewMockConn(t) var written []byte conn.EXPECT().Write(mock.Anything).RunAndReturn(func(b []byte) (int, error) { written = b return len(b), nil }).Maybe() req := models.Request{ ID: 123, Method: "plugins.install", Params: map[string]any{ "name": 123, }, } HandleInstall(conn, req) var resp models.Response[SuccessResult] err := json.Unmarshal(written, &resp) assert.NoError(t, err) assert.NotEmpty(t, resp.Error) } func TestHandleUninstallMissingName(t *testing.T) { conn := net.NewMockConn(t) var written []byte conn.EXPECT().Write(mock.Anything).RunAndReturn(func(b []byte) (int, error) { written = b return len(b), nil }).Maybe() req := models.Request{ ID: 123, Method: "plugins.uninstall", Params: map[string]any{}, } HandleUninstall(conn, req) var resp models.Response[SuccessResult] err := json.Unmarshal(written, &resp) assert.NoError(t, err) assert.NotEmpty(t, resp.Error) } func TestHandleUpdateMissingName(t *testing.T) { conn := net.NewMockConn(t) var written []byte conn.EXPECT().Write(mock.Anything).RunAndReturn(func(b []byte) (int, error) { written = b return len(b), nil }).Maybe() req := models.Request{ ID: 123, Method: "plugins.update", Params: map[string]any{}, } HandleUpdate(conn, req) var resp models.Response[SuccessResult] err := json.Unmarshal(written, &resp) assert.NoError(t, err) assert.NotEmpty(t, resp.Error) } func TestHandleSearchMissingQuery(t *testing.T) { conn := net.NewMockConn(t) var written []byte conn.EXPECT().Write(mock.Anything).RunAndReturn(func(b []byte) (int, error) { written = b return len(b), nil }).Maybe() req := models.Request{ ID: 123, Method: "plugins.search", Params: map[string]any{}, } HandleSearch(conn, req) var resp models.Response[[]PluginInfo] err := json.Unmarshal(written, &resp) assert.NoError(t, err) assert.NotEmpty(t, resp.Error) } func TestSortPluginInfoByFirstParty(t *testing.T) { plugins := []PluginInfo{ {Name: "third-party", Repo: "https://github.com/other/test"}, {Name: "first-party", Repo: "https://github.com/AvengeMedia/test"}, } SortPluginInfoByFirstParty(plugins) assert.Equal(t, "first-party", plugins[0].Name) assert.Equal(t, "third-party", plugins[1].Name) } func TestPluginInfoJSON(t *testing.T) { info := PluginInfo{ Name: "test", Description: "test description", Screenshot: "https://raw.githubusercontent.com/test/repo/main/screenshot.png", Installed: true, FirstParty: true, } data, err := json.Marshal(info) assert.NoError(t, err) var unmarshaled PluginInfo err = json.Unmarshal(data, &unmarshaled) assert.NoError(t, err) assert.Equal(t, info.Name, unmarshaled.Name) assert.Equal(t, info.Installed, unmarshaled.Installed) assert.Equal(t, info.Screenshot, unmarshaled.Screenshot) } func TestNormalizeScreenshotURL(t *testing.T) { tests := []struct { name string raw string want string }{ { name: "raw github url is unchanged", raw: "https://raw.githubusercontent.com/alcxyz/DankVault/main/docs/screenshot.png", want: "https://raw.githubusercontent.com/alcxyz/DankVault/main/docs/screenshot.png", }, { name: "github blob url becomes raw content url", raw: "https://github.com/acmagn/DMS-UPS-Monitor/blob/main/assets/screenshot.png", want: "https://raw.githubusercontent.com/acmagn/DMS-UPS-Monitor/main/assets/screenshot.png", }, { name: "github raw url becomes raw content url", raw: "https://github.com/antonjah/nix-monitor/raw/master/assets/scrot.png", want: "https://raw.githubusercontent.com/antonjah/nix-monitor/master/assets/scrot.png", }, { name: "non github url is unchanged", raw: "https://example.com/screenshot.png", want: "https://example.com/screenshot.png", }, { name: "empty url is empty", raw: " ", want: "", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { assert.Equal(t, tt.want, normalizeScreenshotURL(tt.raw)) }) } } func TestPluginInfoFromPluginIncludesScreenshot(t *testing.T) { info := pluginInfoFromPlugin(coreplugins.Plugin{ ID: "dankVault", Name: "Vault", Repo: "https://github.com/AvengeMedia/dms-plugins", Screenshot: "https://github.com/AvengeMedia/dms-plugins/blob/master/DankNotepadModule/screenshot.png", }) assert.Equal(t, "https://raw.githubusercontent.com/AvengeMedia/dms-plugins/master/DankNotepadModule/screenshot.png", info.Screenshot) assert.True(t, info.FirstParty) } func TestSuccessResult(t *testing.T) { result := SuccessResult{ Success: true, Message: "test message", } data, err := json.Marshal(result) assert.NoError(t, err) var unmarshaled SuccessResult err = json.Unmarshal(data, &unmarshaled) assert.NoError(t, err) assert.True(t, unmarshaled.Success) assert.Equal(t, "test message", unmarshaled.Message) }