Files
galaxy-game/mail/contract_asyncapi_test.go
T
2026-04-17 18:39:16 +02:00

190 lines
6.1 KiB
Go

package mail
import (
"os"
"path/filepath"
"runtime"
"testing"
"gopkg.in/yaml.v3"
"github.com/stretchr/testify/require"
)
func TestDeliveryCommandsAsyncAPISpecLoads(t *testing.T) {
t.Parallel()
doc := loadAsyncAPISpec(t)
require.Equal(t, "3.1.0", getStringValue(t, doc, "asyncapi"))
}
func TestDeliveryCommandsAsyncAPISpecFreezesChannelAndOperation(t *testing.T) {
t.Parallel()
doc := loadAsyncAPISpec(t)
channel := getMapValue(t, doc, "channels", "deliveryCommands")
require.Equal(t, "mail:delivery_commands", getStringValue(t, channel, "address"))
channelMessages := getMapValue(t, channel, "messages")
require.Equal(t, "#/components/messages/RenderedDeliveryCommand", getStringValue(t, getMapValue(t, channelMessages, "renderedDeliveryCommand"), "$ref"))
require.Equal(t, "#/components/messages/TemplateDeliveryCommand", getStringValue(t, getMapValue(t, channelMessages, "templateDeliveryCommand"), "$ref"))
operation := getMapValue(t, doc, "operations", "publishDeliveryCommand")
require.Equal(t, "send", getStringValue(t, operation, "action"))
require.Equal(t, "#/channels/deliveryCommands", getStringValue(t, getMapValue(t, operation, "channel"), "$ref"))
messageRefs := getSliceValue(t, operation, "messages")
require.Len(t, messageRefs, 2)
require.Equal(t, "#/channels/deliveryCommands/messages/renderedDeliveryCommand", getStringValue(t, messageRefs[0].(map[string]any), "$ref"))
require.Equal(t, "#/channels/deliveryCommands/messages/templateDeliveryCommand", getStringValue(t, messageRefs[1].(map[string]any), "$ref"))
}
func TestDeliveryCommandsAsyncAPISpecFreezesEnvelopeSchemas(t *testing.T) {
t.Parallel()
doc := loadAsyncAPISpec(t)
schemas := getMapValue(t, getMapValue(t, doc, "components"), "schemas")
renderedEnvelope := getMapValue(t, schemas, "RenderedDeliveryCommandEnvelope")
require.ElementsMatch(
t,
[]any{"delivery_id", "source", "payload_mode", "idempotency_key", "requested_at_ms", "payload_json"},
getSliceValue(t, renderedEnvelope, "required"),
)
require.Equal(t, "notification", getScalarValue(t, getMapValue(t, getMapValue(t, renderedEnvelope, "properties"), "source"), "const"))
require.Equal(t, "rendered", getScalarValue(t, getMapValue(t, getMapValue(t, renderedEnvelope, "properties"), "payload_mode"), "const"))
require.Equal(
t,
"#/components/schemas/RenderedPayloadJSON",
getStringValue(t, getMapValue(t, getMapValue(t, getMapValue(t, renderedEnvelope, "properties"), "payload_json"), "contentSchema"), "$ref"),
)
templateEnvelope := getMapValue(t, schemas, "TemplateDeliveryCommandEnvelope")
require.Equal(t, "notification", getScalarValue(t, getMapValue(t, getMapValue(t, templateEnvelope, "properties"), "source"), "const"))
require.Equal(t, "template", getScalarValue(t, getMapValue(t, getMapValue(t, templateEnvelope, "properties"), "payload_mode"), "const"))
require.Equal(
t,
"#/components/schemas/TemplatePayloadJSON",
getStringValue(t, getMapValue(t, getMapValue(t, getMapValue(t, templateEnvelope, "properties"), "payload_json"), "contentSchema"), "$ref"),
)
}
func TestDeliveryCommandsAsyncAPISpecFreezesPayloadSchemasAndExamples(t *testing.T) {
t.Parallel()
doc := loadAsyncAPISpec(t)
components := getMapValue(t, doc, "components")
schemas := getMapValue(t, components, "schemas")
messages := getMapValue(t, components, "messages")
renderedPayload := getMapValue(t, schemas, "RenderedPayloadJSON")
require.ElementsMatch(
t,
[]any{"to", "cc", "bcc", "reply_to", "subject", "text_body", "attachments"},
getSliceValue(t, renderedPayload, "required"),
)
templatePayload := getMapValue(t, schemas, "TemplatePayloadJSON")
require.ElementsMatch(
t,
[]any{"to", "cc", "bcc", "reply_to", "template_id", "locale", "variables", "attachments"},
getSliceValue(t, templatePayload, "required"),
)
attachment := getMapValue(t, schemas, "Attachment")
require.ElementsMatch(
t,
[]any{"filename", "content_type", "content_base64"},
getSliceValue(t, attachment, "required"),
)
renderedExamples := getSliceValue(t, getMapValue(t, messages, "RenderedDeliveryCommand"), "examples")
require.NotEmpty(t, getStringValue(t, getMapValue(t, renderedExamples[0].(map[string]any), "payload"), "payload_json"))
templateExamples := getSliceValue(t, getMapValue(t, messages, "TemplateDeliveryCommand"), "examples")
require.NotEmpty(t, getStringValue(t, getMapValue(t, templateExamples[0].(map[string]any), "payload"), "payload_json"))
}
func loadAsyncAPISpec(t *testing.T) map[string]any {
t.Helper()
_, thisFile, _, ok := runtime.Caller(0)
if !ok {
require.FailNow(t, "runtime.Caller failed")
}
specPath := filepath.Join(filepath.Dir(thisFile), "api", "delivery-commands-asyncapi.yaml")
payload, err := os.ReadFile(specPath)
if err != nil {
require.Failf(t, "test failed", "read spec %s: %v", specPath, err)
}
var doc map[string]any
if err := yaml.Unmarshal(payload, &doc); err != nil {
require.Failf(t, "test failed", "decode spec %s: %v", specPath, err)
}
return doc
}
func getMapValue(t *testing.T, value map[string]any, path ...string) map[string]any {
t.Helper()
current := value
for _, segment := range path {
raw, ok := current[segment]
if !ok {
require.Failf(t, "test failed", "missing map key %s", segment)
}
next, ok := raw.(map[string]any)
if !ok {
require.Failf(t, "test failed", "value at %s is not a map", segment)
}
current = next
}
return current
}
func getStringValue(t *testing.T, value map[string]any, key string) string {
t.Helper()
raw, ok := value[key]
if !ok {
require.Failf(t, "test failed", "missing key %s", key)
}
result, ok := raw.(string)
if !ok {
require.Failf(t, "test failed", "value at %s is not a string", key)
}
return result
}
func getScalarValue(t *testing.T, value map[string]any, key string) any {
t.Helper()
raw, ok := value[key]
if !ok {
require.Failf(t, "test failed", "missing key %s", key)
}
return raw
}
func getSliceValue(t *testing.T, value map[string]any, key string) []any {
t.Helper()
raw, ok := value[key]
if !ok {
require.Failf(t, "test failed", "missing key %s", key)
}
result, ok := raw.([]any)
if !ok {
require.Failf(t, "test failed", "value at %s is not a slice", key)
}
return result
}