Files
upstream-ory-kratos/x/events/events_test.go
upstream-mirror c60cc7ca75
Some checks failed
CI / Run tests and lints (push) Failing after 29s
CI / Build CLI docs (push) Has been skipped
CI / Run Playwright end-to-end tests (mysql) (push) Failing after 3s
CI / Run Playwright end-to-end tests (postgres) (push) Failing after 2s
CI / Run Playwright end-to-end tests (sqlite) (push) Failing after 3s
CodeQL / Analyze (go) (push) Failing after 4s
CodeQL / Analyze (javascript) (push) Failing after 3s
Docker Image Scanners / scanners (push) Failing after 4s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Run end-to-end tests (postgres) (push) Failing after 19s
CI / Run end-to-end tests (sqlite) (push) Failing after 2s
CI / Run Playwright end-to-end tests (cockroach) (push) Failing after 2s
CI / Draft newsletter (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
snapshot of https://github.com/ory/kratos.git (master, 2026-09-15; blobs > 131072B omitted)
2026-09-15 21:19:12 +05:00

271 lines
9.2 KiB
Go

// Copyright © 2025 Ory Corp
// SPDX-License-Identifier: Apache-2.0
package events_test
import (
"errors"
"testing"
"github.com/gofrs/uuid"
"github.com/stretchr/testify/assert"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"github.com/ory/kratos/identity"
"github.com/ory/kratos/x"
"github.com/ory/kratos/x/events"
"github.com/ory/x/otelx/semconv"
)
func TestNewJsonnetMappingFailed(t *testing.T) {
tests := []struct {
name string
err error
jsonnetInput []byte
jsonnetOutput string
provider string
method identity.CredentialsType
expectedAttrs []attribute.KeyValue
}{
{
name: "With all attributes",
err: errors.New("test error"),
jsonnetInput: []byte(`{"key": "PII value"}`),
jsonnetOutput: `{"key": 123}`,
provider: "test-provider",
method: identity.CredentialsTypeOIDC,
expectedAttrs: []attribute.KeyValue{
attribute.String("SelfServiceSSOProviderUsed", "test-provider"),
attribute.String("SelfServiceMethodUsed", "oidc"),
attribute.String("ErrorReason", "test error"),
attribute.String("JsonnetInput", `{
"key": "string"
}`),
attribute.String("JsonnetOutput", `{
"key": "number"
}`),
},
},
{
name: "Without JsonnetOutput",
err: errors.New("another error"),
jsonnetInput: []byte(`{"key": "PII value"}`),
jsonnetOutput: "",
provider: "another-provider",
method: identity.CredentialsTypeSAML,
expectedAttrs: []attribute.KeyValue{
attribute.String("SelfServiceSSOProviderUsed", "another-provider"),
attribute.String("SelfServiceMethodUsed", "saml"),
attribute.String("ErrorReason", "another error"),
attribute.String("JsonnetInput", `{
"key": "string"
}`),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := t.Context()
eventName, opts := events.NewJsonnetMappingFailed(ctx, tt.err, tt.jsonnetInput, tt.jsonnetOutput, tt.provider, tt.method.String())
assert.Equal(t, events.JsonnetMappingFailed.String(), eventName)
eventConfig := trace.NewEventConfig(opts)
assert.ElementsMatch(t, tt.expectedAttrs, eventConfig.Attributes())
})
}
}
func TestNewLoginFailed(t *testing.T) {
ctx := t.Context()
flowID := uuid.Must(uuid.NewV4())
identityID := uuid.Must(uuid.NewV4())
baseErr := errors.New("login failed")
t.Run("case=without identity ID", func(t *testing.T) {
eventName, opts := events.NewLoginFailed(ctx, flowID, "browser", "password", "aal1", false, baseErr)
assert.Equal(t, events.LoginFailed.String(), eventName)
eventConfig := trace.NewEventConfig(opts)
attrs := eventConfig.Attributes()
// Should not contain IdentityID attribute
for _, attr := range attrs {
assert.NotEqual(t, "IdentityID", string(attr.Key))
}
// Should contain other attributes
assert.Contains(t, attrs, attribute.String("SelfServiceFlowType", "browser"))
assert.Contains(t, attrs, attribute.String("LoginRequestedAAL", "aal1"))
assert.Contains(t, attrs, attribute.Bool("LoginRequestedPrivilegedSession", false))
assert.Contains(t, attrs, attribute.String("ErrorReason", "login failed"))
assert.Contains(t, attrs, attribute.String("SelfServiceMethodUsed", "password"))
})
t.Run("case=with identity ID", func(t *testing.T) {
wrappedErr := x.WrapWithIdentityIDError(baseErr, identityID)
eventName, opts := events.NewLoginFailed(ctx, flowID, "browser", "password", "aal1", false, wrappedErr)
assert.Equal(t, events.LoginFailed.String(), eventName)
eventConfig := trace.NewEventConfig(opts)
attrs := eventConfig.Attributes()
assert.Contains(t, attrs, attribute.String("IdentityID", identityID.String()))
assert.Contains(t, attrs, attribute.String("SelfServiceFlowType", "browser"))
assert.Contains(t, attrs, attribute.String("ErrorReason", "login failed"))
})
}
func TestNewRecoveryFailed(t *testing.T) {
ctx := t.Context()
flowID := uuid.Must(uuid.NewV4())
identityID := uuid.Must(uuid.NewV4())
baseErr := errors.New("recovery failed")
t.Run("case=without identity ID", func(t *testing.T) {
eventName, opts := events.NewRecoveryFailed(ctx, flowID, "browser", "code", baseErr)
assert.Equal(t, events.RecoveryFailed.String(), eventName)
eventConfig := trace.NewEventConfig(opts)
attrs := eventConfig.Attributes()
for _, attr := range attrs {
assert.NotEqual(t, "IdentityID", string(attr.Key))
}
assert.Contains(t, attrs, attribute.String("SelfServiceFlowType", "browser"))
assert.Contains(t, attrs, attribute.String("SelfServiceMethodUsed", "code"))
})
t.Run("case=with identity ID", func(t *testing.T) {
wrappedErr := x.WrapWithIdentityIDError(baseErr, identityID)
eventName, opts := events.NewRecoveryFailed(ctx, flowID, "browser", "link", wrappedErr)
assert.Equal(t, events.RecoveryFailed.String(), eventName)
eventConfig := trace.NewEventConfig(opts)
attrs := eventConfig.Attributes()
assert.Contains(t, attrs, attribute.String("IdentityID", identityID.String()))
assert.Contains(t, attrs, attribute.String("SelfServiceFlowType", "browser"))
assert.Contains(t, attrs, attribute.String("SelfServiceMethodUsed", "link"))
})
}
func TestNewSettingsFailed(t *testing.T) {
ctx := t.Context()
flowID := uuid.Must(uuid.NewV4())
identityID := uuid.Must(uuid.NewV4())
baseErr := errors.New("settings failed")
t.Run("case=without identity ID", func(t *testing.T) {
eventName, opts := events.NewSettingsFailed(ctx, flowID, "browser", "profile", baseErr)
assert.Equal(t, events.SettingsFailed.String(), eventName)
eventConfig := trace.NewEventConfig(opts)
attrs := eventConfig.Attributes()
for _, attr := range attrs {
assert.NotEqual(t, "IdentityID", string(attr.Key))
}
assert.Contains(t, attrs, attribute.String("SelfServiceFlowType", "browser"))
assert.Contains(t, attrs, attribute.String("SelfServiceMethodUsed", "profile"))
})
t.Run("case=with identity ID", func(t *testing.T) {
wrappedErr := x.WrapWithIdentityIDError(baseErr, identityID)
eventName, opts := events.NewSettingsFailed(ctx, flowID, "browser", "password", wrappedErr)
assert.Equal(t, events.SettingsFailed.String(), eventName)
eventConfig := trace.NewEventConfig(opts)
attrs := eventConfig.Attributes()
assert.Contains(t, attrs, attribute.String("IdentityID", identityID.String()))
assert.Contains(t, attrs, attribute.String("SelfServiceFlowType", "browser"))
assert.Contains(t, attrs, attribute.String("SelfServiceMethodUsed", "password"))
})
}
func TestNewVerificationFailed(t *testing.T) {
ctx := t.Context()
flowID := uuid.Must(uuid.NewV4())
identityID := uuid.Must(uuid.NewV4())
baseErr := errors.New("verification failed")
t.Run("case=without identity ID", func(t *testing.T) {
eventName, opts := events.NewVerificationFailed(ctx, flowID, "browser", "code", baseErr)
assert.Equal(t, events.VerificationFailed.String(), eventName)
eventConfig := trace.NewEventConfig(opts)
attrs := eventConfig.Attributes()
for _, attr := range attrs {
assert.NotEqual(t, "IdentityID", string(attr.Key))
}
assert.Contains(t, attrs, attribute.String("SelfServiceFlowType", "browser"))
assert.Contains(t, attrs, attribute.String("SelfServiceMethodUsed", "code"))
})
t.Run("case=with identity ID", func(t *testing.T) {
wrappedErr := x.WrapWithIdentityIDError(baseErr, identityID)
eventName, opts := events.NewVerificationFailed(ctx, flowID, "browser", "link", wrappedErr)
assert.Equal(t, events.VerificationFailed.String(), eventName)
eventConfig := trace.NewEventConfig(opts)
attrs := eventConfig.Attributes()
assert.Contains(t, attrs, attribute.String("IdentityID", identityID.String()))
assert.Contains(t, attrs, attribute.String("SelfServiceFlowType", "browser"))
assert.Contains(t, attrs, attribute.String("SelfServiceMethodUsed", "link"))
})
}
func TestNewCourierMessageDispatched(t *testing.T) {
t.Parallel()
nid := uuid.Must(uuid.NewV4())
msgID := uuid.Must(uuid.NewV4())
ctx := semconv.ContextWithAttributes(t.Context(), attribute.String("ProjectID", nid.String()))
eventName, opts := events.NewCourierMessageDispatched(ctx, msgID, "smtp", "stub")
assert.Equal(t, events.CourierMessageDispatched.String(), eventName)
eventConfig := trace.NewEventConfig(opts)
attrs := eventConfig.Attributes()
assert.Contains(t, attrs, attribute.String("ProjectID", nid.String()))
assert.Contains(t, attrs, attribute.String("CourierMessageID", msgID.String()))
assert.Contains(t, attrs, attribute.String("CourierMessageChannel", "smtp"))
assert.Contains(t, attrs, attribute.String("CourierMessageTemplateType", "stub"))
}
func TestNewCourierMessageAbandoned(t *testing.T) {
t.Parallel()
nid := uuid.Must(uuid.NewV4())
msgID := uuid.Must(uuid.NewV4())
ctx := semconv.ContextWithAttributes(t.Context(), attribute.String("ProjectID", nid.String()))
eventName, opts := events.NewCourierMessageAbandoned(ctx, msgID, "http", "recovery")
assert.Equal(t, events.CourierMessageAbandoned.String(), eventName)
eventConfig := trace.NewEventConfig(opts)
attrs := eventConfig.Attributes()
assert.Contains(t, attrs, attribute.String("ProjectID", nid.String()))
assert.Contains(t, attrs, attribute.String("CourierMessageID", msgID.String()))
assert.Contains(t, attrs, attribute.String("CourierMessageChannel", "http"))
assert.Contains(t, attrs, attribute.String("CourierMessageTemplateType", "recovery"))
}