Files
phishingclub/backend/service/templateService_flowurl_test.go
2026-08-10 20:57:32 +02:00

94 lines
2.9 KiB
Go

package service
import (
"net/url"
"testing"
"github.com/google/uuid"
"github.com/phishingclub/phishingclub/data"
"github.com/phishingclub/phishingclub/utils"
)
// decryptState pulls the state parameter out of a built flow url and decrypts it back to
// the page type it encodes, so the test can assert the url points at the right stage.
func decryptState(t *testing.T, rawURL string, stateKey string, secret string) string {
t.Helper()
parsed, err := url.Parse(rawURL)
if err != nil {
t.Fatalf("failed to parse url %q: %v", rawURL, err)
}
state := parsed.Query().Get(stateKey)
if state == "" {
t.Fatalf("url %q has no %q state param", rawURL, stateKey)
}
page, err := utils.Decrypt(state, secret)
if err != nil {
t.Fatalf("failed to decrypt state %q: %v", state, err)
}
return page
}
func TestBuildFlowPageURLs(t *testing.T) {
campaignID := uuid.New()
secret := utils.UUIDToSecret(&campaignID)
crid := uuid.New().String()
base := FlowPageURLParams{
BaseURL: "https://example.test",
URLPath: "/login",
URLIdentifier: "id",
StateIdentifier: "state",
CampaignRecipientID: crid,
CampaignID: campaignID,
}
t.Run("all stages present", func(t *testing.T) {
p := base
p.HasBeforePage = true
p.HasAfterPage = true
before, landing, after := BuildFlowPageURLs(p)
for name, u := range map[string]string{"before": before, "landing": landing, "after": after} {
if u == "" {
t.Fatalf("%s url is empty, expected a value", name)
}
parsed, err := url.Parse(u)
if err != nil {
t.Fatalf("%s url %q did not parse: %v", name, u, err)
}
if got := parsed.Query().Get("id"); got != crid {
t.Errorf("%s url id param = %q, want %q", name, got, crid)
}
if parsed.Path != "/login" {
t.Errorf("%s url path = %q, want /login", name, parsed.Path)
}
}
if got := decryptState(t, before, "state", secret); got != data.PAGE_TYPE_BEFORE {
t.Errorf("before state = %q, want %q", got, data.PAGE_TYPE_BEFORE)
}
if got := decryptState(t, landing, "state", secret); got != data.PAGE_TYPE_LANDING {
t.Errorf("landing state = %q, want %q", got, data.PAGE_TYPE_LANDING)
}
if got := decryptState(t, after, "state", secret); got != data.PAGE_TYPE_AFTER {
t.Errorf("after state = %q, want %q", got, data.PAGE_TYPE_AFTER)
}
})
t.Run("no before or after stage renders empty", func(t *testing.T) {
before, landing, after := BuildFlowPageURLs(base)
if before != "" {
t.Errorf("before url = %q, want empty when stage absent", before)
}
if after != "" {
t.Errorf("after url = %q, want empty when stage absent", after)
}
if landing == "" {
t.Fatal("landing url is empty, want a value since landing is always present")
}
if got := decryptState(t, landing, "state", secret); got != data.PAGE_TYPE_LANDING {
t.Errorf("landing state = %q, want %q", got, data.PAGE_TYPE_LANDING)
}
})
}