Files
argoyle 862060875b test: add validation and event tests for organization and API key
Adds unit tests for the `AddOrganization` and `AddAPIKey` commands. 
These tests validate various scenarios, including success cases, 
handling of already existing organizations or keys, and ensuring 
required fields are checked. The
changes enhance test coverage and ensure robustness of the command 
logic.
2025-11-21 12:49:23 +01:00

435 lines
8.0 KiB
Go

package sdlmerge
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestMergeSDLs_Success(t *testing.T) {
// Both types need to be in the same subgraph or properly federated
sdl1 := `
type User {
id: ID!
name: String!
}
type Post {
id: ID!
title: String!
}
`
result, err := MergeSDLs(sdl1)
require.NoError(t, err)
assert.Contains(t, result, "User")
assert.Contains(t, result, "Post")
assert.Contains(t, result, "id")
assert.Contains(t, result, "name")
assert.Contains(t, result, "title")
}
func TestMergeSDLs_SingleSchema(t *testing.T) {
sdl := `
type Query {
hello: String
}
`
result, err := MergeSDLs(sdl)
require.NoError(t, err)
assert.Contains(t, result, "Query")
assert.Contains(t, result, "hello")
}
func TestMergeSDLs_EmptySchemas(t *testing.T) {
result, err := MergeSDLs()
require.NoError(t, err)
// With no schemas, result will be empty after processing
// This is valid - just verifies no crash
_ = result
}
func TestMergeSDLs_InvalidSyntax(t *testing.T) {
invalidSDL := `
type User {
id: ID!
name: String!
// Missing closing brace
`
_, err := MergeSDLs(invalidSDL)
require.Error(t, err)
assert.Contains(t, err.Error(), "parse graphql document string")
}
func TestMergeSDLs_UnknownType(t *testing.T) {
sdl := `
type User {
id: ID!
profile: UnknownType
}
`
_, err := MergeSDLs(sdl)
require.Error(t, err)
assert.Contains(t, err.Error(), "validate schema")
}
func TestMergeSDLs_DuplicateTypes_DifferentFields(t *testing.T) {
// Same type with different fields in different subgraphs - should fail
// In federation, shared types must be identical
sdl1 := `
type User {
id: ID!
}
`
sdl2 := `
type User {
name: String!
}
`
_, err := MergeSDLs(sdl1, sdl2)
require.Error(t, err)
assert.Contains(t, err.Error(), "shared type")
}
func TestMergeSDLs_ExtendType(t *testing.T) {
sdl1 := `
type User {
id: ID!
}
`
sdl2 := `
extend type User {
email: String!
}
`
result, err := MergeSDLs(sdl1, sdl2)
require.NoError(t, err)
assert.Contains(t, result, "User")
assert.Contains(t, result, "id")
assert.Contains(t, result, "email")
}
func TestMergeSDLs_Scalars(t *testing.T) {
sdl := `
scalar DateTime
type Event {
id: ID!
createdAt: DateTime!
}
`
result, err := MergeSDLs(sdl)
require.NoError(t, err)
assert.Contains(t, result, "DateTime")
assert.Contains(t, result, "Event")
}
func TestMergeSDLs_Enums(t *testing.T) {
sdl := `
enum Role {
ADMIN
USER
GUEST
}
type User {
id: ID!
role: Role!
}
`
result, err := MergeSDLs(sdl)
require.NoError(t, err)
assert.Contains(t, result, "Role")
assert.Contains(t, result, "ADMIN")
assert.Contains(t, result, "USER")
}
func TestMergeSDLs_Interfaces(t *testing.T) {
sdl := `
interface Node {
id: ID!
}
type User implements Node {
id: ID!
name: String!
}
`
result, err := MergeSDLs(sdl)
require.NoError(t, err)
assert.Contains(t, result, "Node")
assert.Contains(t, result, "implements")
}
func TestMergeSDLs_Unions(t *testing.T) {
sdl := `
type User {
id: ID!
name: String!
}
type Bot {
id: ID!
version: String!
}
union Actor = User | Bot
`
result, err := MergeSDLs(sdl)
require.NoError(t, err)
assert.Contains(t, result, "Actor")
assert.Contains(t, result, "User")
assert.Contains(t, result, "Bot")
}
func TestMergeSDLs_InputTypes(t *testing.T) {
sdl := `
input CreateUserInput {
name: String!
email: String!
}
type Mutation {
createUser(input: CreateUserInput!): User
}
type User {
id: ID!
name: String!
}
`
result, err := MergeSDLs(sdl)
require.NoError(t, err)
assert.Contains(t, result, "CreateUserInput")
assert.Contains(t, result, "createUser")
}
func TestMergeSDLs_Directives(t *testing.T) {
sdl := `
type User {
id: ID!
name: String! @deprecated(reason: "Use fullName instead")
fullName: String!
}
`
result, err := MergeSDLs(sdl)
require.NoError(t, err)
assert.Contains(t, result, "User")
assert.Contains(t, result, "name")
assert.Contains(t, result, "fullName")
}
func TestMergeSDLs_FederationKeys(t *testing.T) {
// Federation @key directive
sdl := `
type User @key(fields: "id") {
id: ID!
name: String!
}
`
result, err := MergeSDLs(sdl)
require.NoError(t, err)
assert.Contains(t, result, "User")
// @key directive should be removed during merge
assert.NotContains(t, result, "@key")
}
func TestMergeSDLs_ExternalFields(t *testing.T) {
// Federation @external directive
sdl1 := `
type User @key(fields: "id") {
id: ID!
name: String!
}
`
sdl2 := `
extend type User @key(fields: "id") {
id: ID! @external
posts: [Post!]!
}
type Post {
id: ID!
title: String!
}
`
result, err := MergeSDLs(sdl1, sdl2)
require.NoError(t, err)
assert.Contains(t, result, "User")
assert.Contains(t, result, "Post")
// @external fields should be removed
assert.NotContains(t, result, "@external")
}
func TestMergeSDLs_ComplexSchema(t *testing.T) {
// Multiple subgraphs with various types - simplified to avoid cross-references
users := `
type User @key(fields: "id") {
id: ID!
username: String!
email: String!
}
type Query {
user(id: ID!): User
users: [User!]!
}
`
posts := `
extend type User @key(fields: "id") {
id: ID! @external
posts: [Post!]!
}
type Post @key(fields: "id") {
id: ID!
title: String!
content: String!
}
extend type Query {
post(id: ID!): Post
posts: [Post!]!
}
`
comments := `
extend type Post @key(fields: "id") {
id: ID! @external
comments: [Comment!]!
}
type Comment {
id: ID!
text: String!
}
extend type Query {
comment(id: ID!): Comment
}
`
result, err := MergeSDLs(users, posts, comments)
require.NoError(t, err)
// Verify all types are present
assert.Contains(t, result, "User")
assert.Contains(t, result, "Post")
assert.Contains(t, result, "Comment")
assert.Contains(t, result, "Query")
// Verify fields from all subgraphs
assert.Contains(t, result, "username")
assert.Contains(t, result, "posts")
assert.Contains(t, result, "comments")
}
func TestMergeSDLs_EmptyTypeDefinition(t *testing.T) {
sdl := `
type Empty {}
`
_, err := MergeSDLs(sdl)
require.Error(t, err)
// Empty types are invalid in GraphQL
assert.Contains(t, err.Error(), "empty body")
}
func TestMergeSDLs_MultipleValidationErrors(t *testing.T) {
// Schema with multiple errors
sdl := `
type User {
id: ID!
profile: NonExistentType1
settings: NonExistentType2
}
`
_, err := MergeSDLs(sdl)
require.Error(t, err)
}
func TestMergeSDLs_ListTypes(t *testing.T) {
sdl := `
type User {
id: ID!
tags: [String!]!
friends: [User!]
}
`
result, err := MergeSDLs(sdl)
require.NoError(t, err)
assert.Contains(t, result, "User")
assert.Contains(t, result, "tags")
assert.Contains(t, result, "friends")
}
func TestMergeSDLs_NonNullTypes(t *testing.T) {
sdl := `
type User {
id: ID!
name: String!
email: String
}
`
result, err := MergeSDLs(sdl)
require.NoError(t, err)
assert.Contains(t, result, "User")
assert.Contains(t, result, "id")
assert.Contains(t, result, "name")
assert.Contains(t, result, "email")
}
func TestMergeSDLs_Comments(t *testing.T) {
sdl := `
# This is a user type
type User {
# User ID
id: ID!
# User name
name: String!
}
`
result, err := MergeSDLs(sdl)
require.NoError(t, err)
assert.Contains(t, result, "User")
}
func TestMergeSDLs_LargeSchema(t *testing.T) {
// Test with a reasonably large schema to ensure performance
var sdlBuilder strings.Builder
for i := 0; i < 50; i++ {
sdlBuilder.WriteString("type Type")
sdlBuilder.WriteString(strings.Repeat(string(rune('A'+i%26)), 1))
sdlBuilder.WriteString(string(rune('0' + i/26)))
sdlBuilder.WriteString(" { id: ID }\n")
}
result, err := MergeSDLs(sdlBuilder.String())
require.NoError(t, err)
// Verify some types are present
assert.Contains(t, result, "TypeA0")
assert.Contains(t, result, "TypeB0")
assert.Contains(t, result, "TypeC0")
}