0
0
mirror of https://github.com/go-gitea/gitea.git synced 2025-12-08 15:45:27 +01:00
gitea/tests/integration/render_plugin_test.go
2025-12-07 10:25:14 -08:00

196 lines
6.3 KiB
Go

// Copyright 2025 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package integration
import (
"archive/zip"
"bytes"
"fmt"
"mime/multipart"
"net/http"
"path"
"strconv"
"strings"
"testing"
render_model "code.gitea.io/gitea/models/render"
"code.gitea.io/gitea/models/unittest"
"code.gitea.io/gitea/modules/json"
"code.gitea.io/gitea/modules/renderplugin"
"code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/web/middleware"
"code.gitea.io/gitea/tests"
"github.com/PuerkitoBio/goquery"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRenderPluginLifecycle(t *testing.T) {
defer tests.PrepareTestEnv(t)()
require.NoError(t, storage.Clean(renderplugin.Storage()))
t.Cleanup(func() {
_ = storage.Clean(renderplugin.Storage())
})
const pluginID = "itest-plugin"
session := loginUser(t, "user1")
uploadArchive(t, session, "/-/admin/render-plugins/upload", buildRenderPluginArchive(t, pluginID, "Integration Plugin", "1.0.0"))
flash := expectFlashSuccess(t, session)
assert.Contains(t, flash.SuccessMsg, "installed")
row := requireRenderPluginRow(t, session, pluginID)
assert.Equal(t, "1.0.0", row.Version)
assert.False(t, row.Enabled)
postPluginAction(t, session, fmt.Sprintf("/-/admin/render-plugins/%d/enable", row.ID))
flash = expectFlashSuccess(t, session)
assert.Contains(t, flash.SuccessMsg, "enabled")
row = requireRenderPluginRow(t, session, pluginID)
assert.True(t, row.Enabled)
metas := fetchRenderPluginMetadata(t)
require.Len(t, metas, 1)
assert.Equal(t, pluginID, metas[0].ID)
assert.Contains(t, metas[0].EntryURL, "render.js")
MakeRequest(t, NewRequest(t, "GET", metas[0].EntryURL), http.StatusOK)
uploadArchive(t, session, fmt.Sprintf("/-/admin/render-plugins/%d/upgrade", row.ID), buildRenderPluginArchive(t, pluginID, "Integration Plugin", "2.0.0"))
flash = expectFlashSuccess(t, session)
assert.Contains(t, flash.SuccessMsg, "upgraded")
row = requireRenderPluginRow(t, session, pluginID)
assert.Equal(t, "2.0.0", row.Version)
postPluginAction(t, session, fmt.Sprintf("/-/admin/render-plugins/%d/disable", row.ID))
flash = expectFlashSuccess(t, session)
assert.Contains(t, flash.SuccessMsg, "disabled")
row = requireRenderPluginRow(t, session, pluginID)
assert.False(t, row.Enabled)
require.Empty(t, fetchRenderPluginMetadata(t))
postPluginAction(t, session, fmt.Sprintf("/-/admin/render-plugins/%d/delete", row.ID))
flash = expectFlashSuccess(t, session)
assert.Contains(t, flash.SuccessMsg, "deleted")
unittest.AssertNotExistsBean(t, &render_model.Plugin{Identifier: pluginID})
_, err := renderplugin.Storage().Stat(renderplugin.ObjectPath(pluginID, "render.js"))
assert.Error(t, err)
require.Nil(t, findRenderPluginRow(t, session, pluginID))
}
func postPluginAction(t *testing.T, session *TestSession, path string) {
req := NewRequestWithValues(t, "POST", path, map[string]string{
"_csrf": GetUserCSRFToken(t, session),
})
session.MakeRequest(t, req, http.StatusSeeOther)
}
func uploadArchive(t *testing.T, session *TestSession, path string, archive []byte) {
var body bytes.Buffer
writer := multipart.NewWriter(&body)
require.NoError(t, writer.WriteField("_csrf", GetUserCSRFToken(t, session)))
part, err := writer.CreateFormFile("plugin", "plugin.zip")
require.NoError(t, err)
_, err = part.Write(archive)
require.NoError(t, err)
require.NoError(t, writer.Close())
req := NewRequestWithBody(t, "POST", path, bytes.NewReader(body.Bytes()))
req.Header.Set("Content-Type", writer.FormDataContentType())
resp := session.MakeRequest(t, req, http.StatusOK)
doc := NewHTMLParser(t, resp.Body)
token := doc.GetInputValueByName("token")
require.NotEmpty(t, token, "pending upload token not found")
confirmReq := NewRequestWithValues(t, "POST", path+"/confirm", map[string]string{
"_csrf": GetUserCSRFToken(t, session),
"token": token,
})
session.MakeRequest(t, confirmReq, http.StatusSeeOther)
}
func buildRenderPluginArchive(t *testing.T, id, name, version string) []byte {
manifest := fmt.Sprintf(`{
"schemaVersion": 1,
"id": %q,
"name": %q,
"version": %q,
"description": "integration test plugin",
"entry": "render.js",
"filePatterns": ["*.itest"]
}`, id, name, version)
var buf bytes.Buffer
zipWriter := zip.NewWriter(&buf)
file, err := zipWriter.Create("manifest.json")
require.NoError(t, err)
_, err = file.Write([]byte(manifest))
require.NoError(t, err)
file, err = zipWriter.Create("render.js")
require.NoError(t, err)
_, err = file.Write([]byte("export default {render(){}};"))
require.NoError(t, err)
require.NoError(t, zipWriter.Close())
return buf.Bytes()
}
func fetchRenderPluginMetadata(t *testing.T) []renderplugin.Metadata {
resp := MakeRequest(t, NewRequest(t, "GET", "/assets/render-plugins/index.json"), http.StatusOK)
var metas []renderplugin.Metadata
require.NoError(t, json.Unmarshal(resp.Body.Bytes(), &metas))
return metas
}
func expectFlashSuccess(t *testing.T, session *TestSession) *middleware.Flash {
flash := session.GetCookieFlashMessage()
require.NotNil(t, flash, "expected flash message")
require.Empty(t, flash.ErrorMsg)
return flash
}
type renderPluginRow struct {
ID int64
Identifier string
Version string
Enabled bool
}
func requireRenderPluginRow(t *testing.T, session *TestSession, identifier string) *renderPluginRow {
row := findRenderPluginRow(t, session, identifier)
require.NotNil(t, row, "plugin %s not found", identifier)
return row
}
func findRenderPluginRow(t *testing.T, session *TestSession, identifier string) *renderPluginRow {
resp := session.MakeRequest(t, NewRequest(t, "GET", "/-/admin/render-plugins"), http.StatusOK)
doc := NewHTMLParser(t, resp.Body)
var result *renderPluginRow
doc.Find("table tbody tr").EachWithBreak(func(_ int, s *goquery.Selection) bool {
cols := s.Find("td")
if cols.Length() < 6 {
return true
}
idText := strings.TrimSpace(cols.Eq(1).Text())
if idText != identifier {
return true
}
link := cols.Eq(5).Find("a[href]").First()
href, _ := link.Attr("href")
id, err := strconv.ParseInt(path.Base(href), 10, 64)
if err != nil {
return true
}
version := strings.TrimSpace(cols.Eq(2).Text())
enabled := cols.Eq(4).Find(".ui.green").Length() > 0
result = &renderPluginRow{
ID: id,
Identifier: idText,
Version: version,
Enabled: enabled,
}
return false
})
return result
}