chore: Add distant federation server mock (#7115)
Encapsulates the federation server counterpart & makes the test more configurable. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/7115 Reviewed-by: Gusted <gusted@noreply.codeberg.org> Co-authored-by: Michael Jerger <michael.jerger@meissa-gmbh.de> Co-committed-by: Michael Jerger <michael.jerger@meissa-gmbh.de>
This commit is contained in:
parent
c1399947f4
commit
e39b98ea51
|
@ -0,0 +1,117 @@
|
||||||
|
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FederationServerMockPerson struct {
|
||||||
|
ID int64
|
||||||
|
Name string
|
||||||
|
PubKey string
|
||||||
|
}
|
||||||
|
type FederationServerMockRepository struct {
|
||||||
|
ID int64
|
||||||
|
}
|
||||||
|
type FederationServerMock struct {
|
||||||
|
Persons []FederationServerMockPerson
|
||||||
|
Repositories []FederationServerMockRepository
|
||||||
|
LastPost string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFederationServerMockPerson(id int64, name string) FederationServerMockPerson {
|
||||||
|
return FederationServerMockPerson{
|
||||||
|
ID: id,
|
||||||
|
Name: name,
|
||||||
|
PubKey: `"-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA18H5s7N6ItZUAh9tneII\nIuZdTTa3cZlLa/9ejWAHTkcp3WLW+/zbsumlMrWYfBy2/yTm56qasWt38iY4D6ul\n` +
|
||||||
|
`CPiwhAqX3REvVq8tM79a2CEqZn9ka6vuXoDgBg/sBf/BUWqf7orkjUXwk/U0Egjf\nk5jcurF4vqf1u+rlAHH37dvSBaDjNj6Qnj4OP12bjfaY/yvs7+jue/eNXFHjzN4E\n` +
|
||||||
|
`T2H4B/yeKTJ4UuAwTlLaNbZJul2baLlHelJPAsxiYaziVuV5P+IGWckY6RSerRaZ\nAkc4mmGGtjAyfN9aewe+lNVfwS7ElFx546PlLgdQgjmeSwLX8FWxbPE5A/PmaXCs\n` +
|
||||||
|
`nx+nou+3dD7NluULLtdd7K+2x02trObKXCAzmi5/Dc+yKTzpFqEz+hLNCz7TImP/\ncK//NV9Q+X67J9O27baH9R9ZF4zMw8rv2Pg0WLSw1z7lLXwlgIsDapeMCsrxkVO4\n` +
|
||||||
|
`LXX5AQ1xQNtlssnVoUBqBrvZsX2jUUKUocvZqMGuE4hfAgMBAAE=\n-----END PUBLIC KEY-----\n"`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFederationServerMockRepository(id int64) FederationServerMockRepository {
|
||||||
|
return FederationServerMockRepository{
|
||||||
|
ID: id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p FederationServerMockPerson) marshal(host string) string {
|
||||||
|
return fmt.Sprintf(`{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1"],`+
|
||||||
|
`"id":"http://%[1]v/api/activitypub/user-id/%[2]v",`+
|
||||||
|
`"type":"Person",`+
|
||||||
|
`"icon":{"type":"Image","mediaType":"image/png","url":"http://%[1]v/avatars/1bb05d9a5f6675ed0272af9ea193063c"},`+
|
||||||
|
`"url":"http://%[1]v/%[2]v",`+
|
||||||
|
`"inbox":"http://%[1]v/api/activitypub/user-id/%[2]v/inbox",`+
|
||||||
|
`"outbox":"http://%[1]v/api/activitypub/user-id/%[2]v/outbox",`+
|
||||||
|
`"preferredUsername":"%[3]v",`+
|
||||||
|
`"publicKey":{"id":"http://%[1]v/api/activitypub/user-id/%[2]v#main-key",`+
|
||||||
|
`"owner":"http://%[1]v/api/activitypub/user-id/%[2]v",`+
|
||||||
|
`"publicKeyPem":%[4]v}}`, host, p.ID, p.Name, p.PubKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFederationServerMock() *FederationServerMock {
|
||||||
|
return &FederationServerMock{
|
||||||
|
Persons: []FederationServerMockPerson{
|
||||||
|
NewFederationServerMockPerson(15, "stargoose1"),
|
||||||
|
NewFederationServerMockPerson(30, "stargoose2"),
|
||||||
|
},
|
||||||
|
Repositories: []FederationServerMockRepository{
|
||||||
|
NewFederationServerMockRepository(1),
|
||||||
|
},
|
||||||
|
LastPost: "",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (mock *FederationServerMock) DistantServer(t *testing.T) *httptest.Server {
|
||||||
|
federatedRoutes := http.NewServeMux()
|
||||||
|
federatedRoutes.HandleFunc("/.well-known/nodeinfo",
|
||||||
|
func(res http.ResponseWriter, req *http.Request) {
|
||||||
|
// curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/.well-known/nodeinfo
|
||||||
|
// TODO: as soon as content-type will become important: content-type: application/json;charset=utf-8
|
||||||
|
fmt.Fprintf(res, `{"links":[{"href":"http://%s/api/v1/nodeinfo","rel":"http://nodeinfo.diaspora.software/ns/schema/2.1"}]}`, req.Host)
|
||||||
|
})
|
||||||
|
federatedRoutes.HandleFunc("/api/v1/nodeinfo",
|
||||||
|
func(res http.ResponseWriter, req *http.Request) {
|
||||||
|
// curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/api/v1/nodeinfo
|
||||||
|
fmt.Fprint(res, `{"version":"2.1","software":{"name":"forgejo","version":"1.20.0+dev-3183-g976d79044",`+
|
||||||
|
`"repository":"https://codeberg.org/forgejo/forgejo.git","homepage":"https://forgejo.org/"},`+
|
||||||
|
`"protocols":["activitypub"],"services":{"inbound":[],"outbound":["rss2.0"]},`+
|
||||||
|
`"openRegistrations":true,"usage":{"users":{"total":14,"activeHalfyear":2}},"metadata":{}}`)
|
||||||
|
})
|
||||||
|
for _, person := range mock.Persons {
|
||||||
|
federatedRoutes.HandleFunc(fmt.Sprintf("/api/v1/activitypub/user-id/%v", person.ID),
|
||||||
|
func(res http.ResponseWriter, req *http.Request) {
|
||||||
|
// curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/2
|
||||||
|
fmt.Fprint(res, person.marshal(req.Host))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
for _, repository := range mock.Repositories {
|
||||||
|
federatedRoutes.HandleFunc(fmt.Sprintf("/api/v1/activitypub/repository-id/%v/inbox/", repository.ID),
|
||||||
|
func(res http.ResponseWriter, req *http.Request) {
|
||||||
|
if req.Method != "POST" {
|
||||||
|
t.Errorf("POST expected at: %q", req.URL.EscapedPath())
|
||||||
|
}
|
||||||
|
buf := new(strings.Builder)
|
||||||
|
_, err := io.Copy(buf, req.Body)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error reading body: %q", err)
|
||||||
|
}
|
||||||
|
mock.LastPost = buf.String()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
federatedRoutes.HandleFunc("/",
|
||||||
|
func(res http.ResponseWriter, req *http.Request) {
|
||||||
|
t.Errorf("Unhandled request: %q", req.URL.EscapedPath())
|
||||||
|
})
|
||||||
|
federatedSrv := httptest.NewServer(federatedRoutes)
|
||||||
|
return federatedSrv
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
// Copyright 2024, 2025 The Forgejo Authors. All rights reserved.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package integration
|
package integration
|
||||||
|
@ -6,7 +6,6 @@ package integration
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
@ -58,56 +57,8 @@ func TestActivityPubRepositoryInboxValid(t *testing.T) {
|
||||||
defer test.MockVariableValue(&setting.Federation.Enabled, true)()
|
defer test.MockVariableValue(&setting.Federation.Enabled, true)()
|
||||||
defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())()
|
defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())()
|
||||||
|
|
||||||
federatedRoutes := http.NewServeMux()
|
mock := test.NewFederationServerMock()
|
||||||
federatedRoutes.HandleFunc("/.well-known/nodeinfo",
|
federatedSrv := mock.DistantServer(t)
|
||||||
func(res http.ResponseWriter, req *http.Request) {
|
|
||||||
// curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/.well-known/nodeinfo
|
|
||||||
// TODO: as soon as content-type will become important: content-type: application/json;charset=utf-8
|
|
||||||
fmt.Fprintf(res, `{"links":[{"href":"http://%s/api/v1/nodeinfo","rel":"http://nodeinfo.diaspora.software/ns/schema/2.1"}]}`, req.Host)
|
|
||||||
})
|
|
||||||
federatedRoutes.HandleFunc("/api/v1/nodeinfo",
|
|
||||||
func(res http.ResponseWriter, req *http.Request) {
|
|
||||||
// curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/api/v1/nodeinfo
|
|
||||||
fmt.Fprint(res, `{"version":"2.1","software":{"name":"forgejo","version":"1.20.0+dev-3183-g976d79044",`+
|
|
||||||
`"repository":"https://codeberg.org/forgejo/forgejo.git","homepage":"https://forgejo.org/"},`+
|
|
||||||
`"protocols":["activitypub"],"services":{"inbound":[],"outbound":["rss2.0"]},`+
|
|
||||||
`"openRegistrations":true,"usage":{"users":{"total":14,"activeHalfyear":2}},"metadata":{}}`)
|
|
||||||
})
|
|
||||||
federatedRoutes.HandleFunc("/api/v1/activitypub/user-id/15",
|
|
||||||
func(res http.ResponseWriter, req *http.Request) {
|
|
||||||
// curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/2
|
|
||||||
fmt.Fprint(res, `{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1"],`+
|
|
||||||
`"id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/15","type":"Person",`+
|
|
||||||
`"icon":{"type":"Image","mediaType":"image/png","url":"https://federated-repo.prod.meissa.de/avatars/1bb05d9a5f6675ed0272af9ea193063c"},`+
|
|
||||||
`"url":"https://federated-repo.prod.meissa.de/stargoose1","inbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/15/inbox",`+
|
|
||||||
`"outbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/15/outbox","preferredUsername":"stargoose1",`+
|
|
||||||
`"publicKey":{"id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/15#main-key","owner":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/15",`+
|
|
||||||
`"publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEA18H5s7N6ItZUAh9tneII\nIuZdTTa3cZlLa/9ejWAHTkcp3WLW+/zbsumlMrWYfBy2/yTm56qasWt38iY4D6ul\n`+
|
|
||||||
`CPiwhAqX3REvVq8tM79a2CEqZn9ka6vuXoDgBg/sBf/BUWqf7orkjUXwk/U0Egjf\nk5jcurF4vqf1u+rlAHH37dvSBaDjNj6Qnj4OP12bjfaY/yvs7+jue/eNXFHjzN4E\n`+
|
|
||||||
`T2H4B/yeKTJ4UuAwTlLaNbZJul2baLlHelJPAsxiYaziVuV5P+IGWckY6RSerRaZ\nAkc4mmGGtjAyfN9aewe+lNVfwS7ElFx546PlLgdQgjmeSwLX8FWxbPE5A/PmaXCs\n`+
|
|
||||||
`nx+nou+3dD7NluULLtdd7K+2x02trObKXCAzmi5/Dc+yKTzpFqEz+hLNCz7TImP/\ncK//NV9Q+X67J9O27baH9R9ZF4zMw8rv2Pg0WLSw1z7lLXwlgIsDapeMCsrxkVO4\n`+
|
|
||||||
`LXX5AQ1xQNtlssnVoUBqBrvZsX2jUUKUocvZqMGuE4hfAgMBAAE=\n-----END PUBLIC KEY-----\n"}}`)
|
|
||||||
})
|
|
||||||
federatedRoutes.HandleFunc("/api/v1/activitypub/user-id/30",
|
|
||||||
func(res http.ResponseWriter, req *http.Request) {
|
|
||||||
// curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/3
|
|
||||||
fmt.Fprint(res, `{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1"],`+
|
|
||||||
`"id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/30","type":"Person",`+
|
|
||||||
`"icon":{"type":"Image","mediaType":"image/png","url":"https://federated-repo.prod.meissa.de/avatars/9c03f03d1c1f13f21976a22489326fe1"},`+
|
|
||||||
`"url":"https://federated-repo.prod.meissa.de/stargoose2","inbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/30/inbox",`+
|
|
||||||
`"outbox":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/30/outbox","preferredUsername":"stargoose2",`+
|
|
||||||
`"publicKey":{"id":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/30#main-key","owner":"https://federated-repo.prod.meissa.de/api/v1/activitypub/user-id/30",`+
|
|
||||||
`"publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAyv5NytsfqpWXSrwuk8a3\n0W1zE13QJioXb/e3opgN2CfKZkdm3hb+4+mGKoU/rCqegnL9/AO0Aw+R8fCHXx44\n`+
|
|
||||||
`iNkdVpdY8Dzq+tQ9IetPWbyVIBvSzGgvpqfS05JuVPsy8cBX9wByODjr5kq7k1/v\nY1G7E3uh0a/XJc+mZutwGC3gPgR93NSrqsvTPN4wdhCCu9uj02S8OBoKuSYaPkU+\n`+
|
|
||||||
`tZ4CEDpnclAOw/eNiH4x2irMvVtruEgtlTA5K2I4YJrmtGLidus47FCyc8/zEKUh\nAeiD8KWDvqsQgOhUwcQgRxAnYVCoMD9cnE+WFFRHTuQecNlmdNFs3Cr0yKcWjDde\n`+
|
|
||||||
`trvnehW7LfPveGb0tHRHPuVAJpncTOidUR5h/7pqMyvKHzuAHWomm9rEaGUxd/7a\nL1CFjAf39+QIEgu0Anj8mIc7CTiz+DQhDz+0jBOsQ0iDXc5GeBz7X9Xv4Jp966nq\n`+
|
|
||||||
`MUR0GQGXvfZQN9IqMO+WoUVy10Ddhns1EWGlA0x4fecnAgMBAAE=\n-----END PUBLIC KEY-----\n"}}`)
|
|
||||||
})
|
|
||||||
federatedRoutes.HandleFunc("/",
|
|
||||||
func(res http.ResponseWriter, req *http.Request) {
|
|
||||||
t.Errorf("Unhandled request: %q", req.URL.EscapedPath())
|
|
||||||
})
|
|
||||||
federatedSrv := httptest.NewServer(federatedRoutes)
|
|
||||||
defer federatedSrv.Close()
|
defer federatedSrv.Close()
|
||||||
|
|
||||||
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
onGiteaRun(t, func(t *testing.T, u *url.URL) {
|
||||||
|
|
|
@ -5,9 +5,7 @@ package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
@ -21,6 +19,7 @@ import (
|
||||||
fm "code.gitea.io/gitea/modules/forgefed"
|
fm "code.gitea.io/gitea/modules/forgefed"
|
||||||
"code.gitea.io/gitea/modules/optional"
|
"code.gitea.io/gitea/modules/optional"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
"code.gitea.io/gitea/modules/test"
|
||||||
"code.gitea.io/gitea/modules/validation"
|
"code.gitea.io/gitea/modules/validation"
|
||||||
gitea_context "code.gitea.io/gitea/services/context"
|
gitea_context "code.gitea.io/gitea/services/context"
|
||||||
repo_service "code.gitea.io/gitea/services/repository"
|
repo_service "code.gitea.io/gitea/services/repository"
|
||||||
|
@ -278,59 +277,8 @@ func TestRepoFollowing(t *testing.T) {
|
||||||
setting.Federation.Enabled = false
|
setting.Federation.Enabled = false
|
||||||
}()
|
}()
|
||||||
|
|
||||||
federatedRoutes := http.NewServeMux()
|
mock := test.NewFederationServerMock()
|
||||||
federatedRoutes.HandleFunc("/.well-known/nodeinfo",
|
federatedSrv := mock.DistantServer(t)
|
||||||
func(res http.ResponseWriter, req *http.Request) {
|
|
||||||
// curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/.well-known/nodeinfo
|
|
||||||
responseBody := fmt.Sprintf(`{"links":[{"href":"http://%s/api/v1/nodeinfo","rel":"http://nodeinfo.diaspora.software/ns/schema/2.1"}]}`, req.Host)
|
|
||||||
t.Logf("response: %s", responseBody)
|
|
||||||
// TODO: as soon as content-type will become important: content-type: application/json;charset=utf-8
|
|
||||||
fmt.Fprint(res, responseBody)
|
|
||||||
})
|
|
||||||
federatedRoutes.HandleFunc("/api/v1/nodeinfo",
|
|
||||||
func(res http.ResponseWriter, req *http.Request) {
|
|
||||||
// curl -H "Accept: application/json" https://federated-repo.prod.meissa.de/api/v1/nodeinfo
|
|
||||||
responseBody := fmt.Sprintf(`{"version":"2.1","software":{"name":"forgejo","version":"1.20.0+dev-3183-g976d79044",` +
|
|
||||||
`"repository":"https://codeberg.org/forgejo/forgejo.git","homepage":"https://forgejo.org/"},` +
|
|
||||||
`"protocols":["activitypub"],"services":{"inbound":[],"outbound":["rss2.0"]},` +
|
|
||||||
`"openRegistrations":true,"usage":{"users":{"total":14,"activeHalfyear":2}},"metadata":{}}`)
|
|
||||||
fmt.Fprint(res, responseBody)
|
|
||||||
})
|
|
||||||
repo1InboxReceivedLike := false
|
|
||||||
federatedRoutes.HandleFunc("/api/v1/activitypub/repository-id/1/inbox/",
|
|
||||||
func(res http.ResponseWriter, req *http.Request) {
|
|
||||||
if req.Method != "POST" {
|
|
||||||
t.Errorf("Unhandled request: %q", req.URL.EscapedPath())
|
|
||||||
}
|
|
||||||
buf := new(strings.Builder)
|
|
||||||
_, err := io.Copy(buf, req.Body)
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Error reading body: %q", err)
|
|
||||||
}
|
|
||||||
like := fm.ForgeLike{}
|
|
||||||
err = like.UnmarshalJSON([]byte(buf.String()))
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Error unmarshalling ForgeLike: %q", err)
|
|
||||||
}
|
|
||||||
if isValid, err := validation.IsValid(like); !isValid {
|
|
||||||
t.Errorf("ForgeLike is not valid: %q", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
activityType := like.Type
|
|
||||||
object := like.Object.GetLink().String()
|
|
||||||
isLikeType := activityType == "Like"
|
|
||||||
isCorrectObject := strings.HasSuffix(object, "/api/v1/activitypub/repository-id/1")
|
|
||||||
if !isLikeType || !isCorrectObject {
|
|
||||||
t.Errorf("Activity is not a like for this repo")
|
|
||||||
}
|
|
||||||
|
|
||||||
repo1InboxReceivedLike = true
|
|
||||||
})
|
|
||||||
federatedRoutes.HandleFunc("/",
|
|
||||||
func(res http.ResponseWriter, req *http.Request) {
|
|
||||||
t.Errorf("Unhandled request: %q", req.URL.EscapedPath())
|
|
||||||
})
|
|
||||||
federatedSrv := httptest.NewServer(federatedRoutes)
|
|
||||||
defer federatedSrv.Close()
|
defer federatedSrv.Close()
|
||||||
|
|
||||||
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
|
||||||
|
@ -363,8 +311,24 @@ func TestRepoFollowing(t *testing.T) {
|
||||||
req := NewRequestWithValues(t, "POST", link, map[string]string{
|
req := NewRequestWithValues(t, "POST", link, map[string]string{
|
||||||
"_csrf": GetCSRF(t, session, repoLink),
|
"_csrf": GetCSRF(t, session, repoLink),
|
||||||
})
|
})
|
||||||
assert.False(t, repo1InboxReceivedLike)
|
|
||||||
session.MakeRequest(t, req, http.StatusOK)
|
session.MakeRequest(t, req, http.StatusOK)
|
||||||
assert.True(t, repo1InboxReceivedLike)
|
|
||||||
|
// Verify distant server received a like activity
|
||||||
|
like := fm.ForgeLike{}
|
||||||
|
err := like.UnmarshalJSON([]byte(mock.LastPost))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("Error unmarshalling ForgeLike: %q", err)
|
||||||
|
}
|
||||||
|
if isValid, err := validation.IsValid(like); !isValid {
|
||||||
|
t.Errorf("ForgeLike is not valid: %q", err)
|
||||||
|
}
|
||||||
|
activityType := like.Type
|
||||||
|
object := like.Object.GetLink().String()
|
||||||
|
isLikeType := activityType == "Like"
|
||||||
|
isCorrectObject := strings.HasSuffix(object, "/api/v1/activitypub/repository-id/1")
|
||||||
|
if !isLikeType || !isCorrectObject {
|
||||||
|
t.Errorf("Activity is not a like for this repo")
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue