Skip to content

Commit

Permalink
Add cucumber tests for GraphQL APIs
Browse files Browse the repository at this point in the history
  • Loading branch information
sgayangi committed Feb 8, 2024
1 parent c85cfbc commit 4d683b3
Show file tree
Hide file tree
Showing 6 changed files with 474 additions and 16 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,8 @@ public static APIDefinitionValidationResponse validateOpenAPIDefinition(String t
new String(inputByteArray, StandardCharsets.UTF_8),
returnContent);
} else {
throw new APIManagementException("Unsupported extension type of file: " +
fileName,
ExceptionCodes.UNSUPPORTED_GRAPHQL_FILE_EXTENSION);
OASParserUtil.addErrorToValidationResponse(validationResponse,
"Invalid definition file type provided.");
}
}
return validationResponse;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -636,27 +636,33 @@ public static APIDefinitionValidationResponse validateGraphQLSchema(String apiDe
boolean returnGraphQLSchemaContent) {
APIDefinitionValidationResponse validationResponse = new APIDefinitionValidationResponse();
ArrayList<ErrorHandler> errors = new ArrayList<>();
if (apiDefinition == "") {

if (apiDefinition.isBlank()) {
validationResponse.setValid(false);
errors.add(new ErrorItem("Invalid API Definition", "API Definition is empty",
400, 400));
errors.add(ExceptionCodes.GRAPHQL_SCHEMA_CANNOT_BE_NULL);
validationResponse.setErrorItems(errors);
return validationResponse;
}

SchemaParser schemaParser = new SchemaParser();
TypeDefinitionRegistry typeRegistry = schemaParser.parse(apiDefinition);
GraphQLSchema graphQLSchema = UnExecutableSchemaGenerator.makeUnExecutableSchema(typeRegistry);
SchemaValidator schemaValidation = new SchemaValidator();
Set<SchemaValidationError> validationErrors = schemaValidation.validateSchema(graphQLSchema);

if (validationErrors.toArray().length > 0) {
Set<SchemaValidationError> validationErrors = new HashSet<>();
try {
TypeDefinitionRegistry typeRegistry = schemaParser.parse(apiDefinition);
GraphQLSchema graphQLSchema = UnExecutableSchemaGenerator.makeUnExecutableSchema(typeRegistry);
SchemaValidator schemaValidation = new SchemaValidator();
validationErrors = schemaValidation.validateSchema(graphQLSchema);
if (validationErrors.toArray().length > 0) {
validationResponse.setValid(false);
errors.add(ExceptionCodes.API_NOT_GRAPHQL);
validationResponse.setErrorItems(errors);
} else {
validationResponse.setValid(true);
validationResponse.setContent(apiDefinition);
}
} catch (Exception e) {
OASParserUtil.addErrorToValidationResponse(validationResponse, e.getMessage());
validationResponse.setValid(false);
errors.add(new ErrorItem("API Definition Validation Error", "API Definition is invalid", 400, 400));
validationResponse.setErrorItems(errors);
} else {
validationResponse.setValid(true);
validationResponse.setContent(apiDefinition);
}

return validationResponse;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
name: ""
basePath: "/"
version: ""
type: "GRAPHQL"
defaultVersion: false
subscriptionValidation: false
operations:
- target: "hero"
verb: "QUERY"
secured: true
scopes: []
- target: "reviews"
verb: "QUERY"
secured: true
scopes: []
- target: "search"
verb: "QUERY"
secured: true
scopes: []
- target: "character"
verb: "QUERY"
secured: true
scopes: []
- target: "droid"
verb: "QUERY"
secured: true
scopes: []
- target: "human"
verb: "QUERY"
secured: true
scopes: []
- target: "allHumans"
verb: "QUERY"
secured: true
scopes: []
- target: "allDroids"
verb: "QUERY"
secured: true
scopes: []
- target: "allCharacters"
verb: "QUERY"
secured: true
scopes: []
- target: "starship"
verb: "QUERY"
secured: true
scopes: []
- target: "createReview"
verb: "MUTATION"
secured: true
scopes: []
- target: "reviewAdded"
verb: "SUBSCRIPTION"
secured: true
scopes: []
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
schema {
query: Query
mutation: Mutation
subscription: Subscription
}

# The query type, represents all of the entry points into our object graph
type Query {
hero(episode: Episode): Character
reviews(episode: Episode!): [Review]
search(text: String): [SearchResult]
character(id: ID!): Character
droid(id: ID!): Droid
human(id: ID!): Human
allHumans(first: Int): [Human]
allDroids(first: Int): [Droid]
allCharacters(first: Int): [Character]
starship(id: ID!): Starship
}

# The mutation type, represents all updates we can make to our data
type Mutation {
createReview(episode: Episode, review: ReviewInput!): Review
}

# The subscription type, represents all subscriptions we can make to our data
type Subscription {
reviewAdded(episode: Episode): Review
}

# The episodes in the Star Wars trilogy
enum Episode {
# Star Wars Episode IV: A New Hope, released in 1977.
NEWHOPE

# Star Wars Episode V: The Empire Strikes Back, released in 1980.
EMPIRE

# Star Wars Episode VI: Return of the Jedi, released in 1983.
JEDI

# Star Wars Episode III: Revenge of the Sith, released in 2005
SITH
}

# A character from the Star Wars universe
interface Character {
# The ID of the character
id: ID!

# The name of the character
name: String!

# The friends of the character, or an empty list if they have none
friends: [Character]

# The friends of the character exposed as a connection with edges
friendsConnection(first: Int, after: ID): FriendsConnection!

# The movies this character appears in
appearsIn: [Episode]!
}

# Units of height
enum LengthUnit {
# The standard unit around the world
METER

# Primarily used in the United States
FOOT
}

# A humanoid creature from the Star Wars universe
type Human implements Character {
# The ID of the human
id: ID!

# What this human calls themselves
name: String!

# The home planet of the human, or null if unknown
homePlanet: String

# Height in the preferred unit, default is meters
height(unit: LengthUnit = METER): Float

# Mass in kilograms, or null if unknown
mass: Float

# This human's friends, or an empty list if they have none
friends: [Character]

# The friends of the human exposed as a connection with edges
friendsConnection(first: Int, after: ID): FriendsConnection!

# The movies this human appears in
appearsIn: [Episode]!

# A list of starships this person has piloted, or an empty list if none
starships: [Starship]
}

# An autonomous mechanical character in the Star Wars universe
type Droid implements Character {
# The ID of the droid
id: ID!

# What others call this droid
name: String!

# This droid's friends, or an empty list if they have none
friends: [Character]

# The friends of the droid exposed as a connection with edges
friendsConnection(first: Int, after: ID): FriendsConnection!

# The movies this droid appears in
appearsIn: [Episode]!

# This droid's primary function
primaryFunction: String
}

# A connection object for a character's friends
type FriendsConnection {
# The total number of friends
totalCount: Int

# The edges for each of the character's friends.
edges: [FriendsEdge]

# A list of the friends, as a convenience when edges are not needed.
friends: [Character]

# Information for paginating this connection
pageInfo: PageInfo!
}

# An edge object for a character's friends
type FriendsEdge {
# A cursor used for pagination
cursor: ID!

# The character represented by this friendship edge
node: Character
}

# Information for paginating this connection
type PageInfo {
startCursor: ID
endCursor: ID
hasNextPage: Boolean!
}

# Represents a review for a movie
type Review {
# The movie
episode: Episode

# The number of stars this review gave, 1-5
stars: Int!

# Comment about the movie
commentary: String
}

# The input object sent when someone is creating a new review
input ReviewInput {
# 0-5 stars
stars: Int!

# Comment about the movie, optional
commentary: String

# Favorite color, optional
favorite_color: ColorInput
}

# The input object sent when passing in a color
input ColorInput {
red: Int!
green: Int!
blue: Int!
}

type Starship {
# The ID of the starship
id: ID!

# The name of the starship
name: String!

# Length of the starship, along the longest axis
length(unit: LengthUnit = METER): Float

coordinates: [[Float!]!]
}

union SearchResult = Human | Droid | Starship
Loading

0 comments on commit 4d683b3

Please sign in to comment.