Skip to content

Commit

Permalink
updated unit tests & readme
Browse files Browse the repository at this point in the history
  • Loading branch information
ChuckJonas committed Jun 26, 2019
1 parent 4165c4d commit 4fd6d33
Show file tree
Hide file tree
Showing 2 changed files with 225 additions and 55 deletions.
89 changes: 80 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
# apex-graphql-query

A simple library for building GraphQL queries in Salesforce's Apex Language. *Currently only offers parital support.*
A simple library for building GraphQL queries in Salesforce's Apex Language.

## Example:
*some use cases still not supported*

## Examples:

### Query
``` graphql
{
human(id: "1000") {
name
height
address {
city
country
city
country
}
}
}
Expand All @@ -23,14 +26,82 @@ A simple library for building GraphQL queries in Salesforce's Apex Language. *C
GraphQLNode human = new GraphQLNode('human')
.setArguments(new GraphQLArgument('id', '1000'))
.add(new Object[]{
'name',
'height',
new GraphQLNode('address')
.add(new Object[]{ 'city', 'country' })
'name',
'height',
new GraphQLNode('address')
.add(new Object[]{ 'city', 'country' })
});
String qry = human.build();

// create GraphQLQuery without Variables
GraphQLQuery qry = new GraphQLQuery(human, null);
System.debug(qry.query);
```

### Operations

``` graphql
mutation CreateReviewForEpisode($ep: Episode!, $review: ReviewInput!) {
createReview(episode: $ep, review: $review) {
stars
commentary
}
}
```

``` json
{
"ep": "JEDI",
"review": {
"stars": 5,
"commentary": "This is a great movie!"
}
}
```

**Equivalent Apex**
``` java

//Variable DTOs
public class CreateReviewForEpisode{
public String ep { get; set; }
public Review review { get; set; }
}

public class Review{
public Integer stars { get; set; }
public String commentary { get; set; }
}

//Mutation Query
GraphQLNode node = new GraphQLNode('CreateReviewForEpisode')
.setOperation('mutation')
.addArguments(new GraphQLArgument('$ep', 'Episode!', true))
.addArguments(new GraphQLArgument('$review', 'ReviewInput!', true))
.add(
new GraphQLNode('createReview')
.addArguments(new GraphQLArgument[]{
new GraphQLArgument('episode', '$ep', true),
new GraphQLArgument('review', '$review', true)
})
.add(new Object[]{'stars', 'commentary'})
);

CreateReviewForEpisode createReviewVariables = new CreateReviewForEpisode();
createReviewVariables.ep = 'JEDI';
createReviewVariables.review = new Review();
createReviewVariables.review.stars = 5;
createReviewVariables.review.commentary = 'This is a great movie!';

// create GraphQLQuery with Variables
GraphQLQuery qry = new GraphQLQuery(node, createReviewVariables);
String payload = JSON.serialize(qry);

//... POST payload to graphQL service endpoint
```
### Additional Usage

See [Unit Tests](https://github.com/ChuckJonas/apex-graphql-query/blob/master/force-app/main/default/classes/GraphQLQueryTests.cls) for more usage examples.

## Deployment

Choose your own Adventure:
Expand Down
191 changes: 145 additions & 46 deletions force-app/main/default/classes/GraphQLQueryTests.cls
Original file line number Diff line number Diff line change
@@ -1,78 +1,156 @@
// Tests using modified examples from https://graphql.org/learn/queries/
@isTest
public class GraphQLQueryTests {

// {
// hero {
// name
// }
// }
@isTest
private static void readmeExample(){
GraphQLNode human = new GraphQLNode('human')
.addArguments(new GraphQLArgument('id', '1000'))
.add(new Object[]{
'name',
'height',
new GraphQLNode('address')
.add(new Object[]{ 'city', 'country' })
});
GraphQLQuery qry = new GraphQLQuery(human, null);
private static void simpleNode(){
GraphQLNode node = new GraphQLNode('hero')
.add('name');
GraphQLQuery qry = new GraphQLQuery(node, null);
System.assertEquals('{hero{name}}', qry.query.deleteWhitespace());
}

// {
// hero(name: "luke skywalker") {
// id
// }
// }
@isTest
private static void testStringArg(){
GraphQLNode node = new GraphQLNode('hero')
.addArguments(new GraphQLArgument('name', 'luke skywalker'))
.add('id');
GraphQLQuery qry = new GraphQLQuery(node, null);
System.assertEquals('{hero(name:\"luke skywalker\"){id}}', qry.query.remove('\n'));
}

// {
// hero(id: 1000) {
// name
// }
// }
@isTest
private static void simpleNode(){
GraphQLNode n = new GraphQLNode('hello')
.add('world');
System.assertEquals('hello{world}', n.build().deleteWhitespace());
private static void testNumberArg(){
GraphQLNode node = new GraphQLNode('hero')
.addArguments(new GraphQLArgument('id', 1000))
.add('name');
GraphQLQuery qry = new GraphQLQuery(node, null);
System.assertEquals('{hero(id:1000){name}}', qry.query.remove('\n'));
}

// {
// hero(isJedi: true) {
// name
// }
// }
@isTest
private static void testSimpleArgs(){
GraphQLNode n = new GraphQLNode('hello')
.addArguments(new GraphQLArgument('key', 'value'))
.add('world');
System.assertEquals('hello(key:\"value\"){world}', n.build().deleteWhitespace());
private static void testBooleanArg(){
GraphQLNode node = new GraphQLNode('hero')
.addArguments(new GraphQLArgument('isJedi', true))
.add('name');
GraphQLQuery qry = new GraphQLQuery(node, null);
System.assertEquals('{hero(isJedi:true){name}}', qry.query.remove('\n'));
}

// {
// hero(episode: EMPIRE) {
// name
// }
// }
@isTest
private static void testChildArgs(){
GraphQLNode n = new GraphQLNode('hello')
.addArguments(new GraphQLArgument('input', new GraphQLArgument[]{
new GraphQLArgument('key1', 'value1'),
new GraphQLArgument('key2', 'value2')
private static void testStringVariableArg(){
GraphQLNode node = new GraphQLNode('hero')
.addArguments(new GraphQLArgument('episode', 'EMPIRE', true))
.add('name');
GraphQLQuery qry = new GraphQLQuery(node, null);
System.assertEquals('{hero(episode:EMPIRE){name}}', qry.query.remove('\n'));
}

// {
// hero(attr: {droid: false, weapon: "lightsaber"}) {
// name
// }
// }
@isTest
private static void testNestedArgs(){
GraphQLNode node = new GraphQLNode('hero')
.addArguments(new GraphQLArgument('attr', new GraphQLArgument[]{
new GraphQLArgument('droid', false),
new GraphQLArgument('weapon', 'lightsaber')
}))
.add('world');
System.assertEquals('hello(input:{key1:\"value1\", key2:\"value2\"}){world}', n.build().remove('\n'));
.add('name');
GraphQLQuery qry = new GraphQLQuery(node, null);
System.assertEquals('{hero(attr:{droid:false, weapon:\"lightsaber\"}){name}}', qry.query.remove('\n'));
}

// {
// hero(episode: EMPIRE, dies: true}) {
// name
// }
// }
@isTest
private static void testMultipleTopLevelArgs(){
GraphQLNode n = new GraphQLNode('hero')
private static void testMultipleArgs(){
GraphQLNode node = new GraphQLNode('hero')
.addArguments(new GraphQLArgument[]{
new GraphQLArgument('episode', 'EMPIRE', true),
new GraphQLArgument('robot', true)
new GraphQLArgument('dies', true)
})
.add('name');

System.assertEquals('hero(episode:EMPIRE, robot:true){name}', n.build().remove('\n'));
GraphQLQuery qry = new GraphQLQuery(node, null);
System.assertEquals('{hero(episode:EMPIRE, dies:true){name}}', qry.query.remove('\n'));
}

// {
// hero {
// attr {
// weapon
// }
// }
// }
@isTest
private static void testChildNode(){
GraphQLNode n = new GraphQLNode('message')
private static void testNestedNode(){
GraphQLNode node = new GraphQLNode('hero')
.add(
new GraphQLNode('hello').add('world')
new GraphQLNode('attr').add('weapon')
);
System.assertEquals('message{hello{world}}', n.build().deleteWhitespace());
GraphQLQuery qry = new GraphQLQuery(node, null);
System.assertEquals('{hero{attr{weapon}}}', qry.query.remove('\n'));
}

// {
// hero {
// name
// ... on Droid {
// primaryFunction
// }
// }
// }
@isTest
private static void testChildOnType(){
GraphQLNode n = new GraphQLNode('foo')
GraphQLNode node = new GraphQLNode('hero')
.add(new Object[]{
new GraphQLNode('bar')
'name',
new GraphQLNode('Droid')
.setTypeFragment(true)
.add('x')
.add('primaryFunction')
});
System.assertEquals('foo{... on bar{x}}', n.build().remove('\n'));
GraphQLQuery qry = new GraphQLQuery(node, null);
System.assertEquals('{hero{name... on Droid{primaryFunction}}}', qry.query.remove('\n'));
}

// {
// empireHero: hero(episode: EMPIRE) {
// name
// }
// jediHero: hero(episode: JEDI) {
// name
// }
// }
@isTest
private static void testAlias(){
GraphQLNode[] nodes = new GraphQLNode[]{
Expand All @@ -98,6 +176,14 @@ public class GraphQLQueryTests {
// commentary
// }
// }
// == Variables ==
// {
// "ep": "JEDI",
// "review": {
// "stars": 5,
// "commentary": "This is a great movie!"
// }
// }
@isTest
private static void testOperation(){
GraphQLNode node = new GraphQLNode('CreateReviewForEpisode')
Expand All @@ -113,17 +199,30 @@ public class GraphQLQueryTests {
.add(new Object[]{'stars', 'commentary'})
);

TestVariables test = new TestVariables();
GraphQLQuery qry = new GraphQLQuery(node, test);
CreateReviewForEpisode createReviewVariables = new CreateReviewForEpisode();
createReviewVariables.ep = 'JEDI';
createReviewVariables.review = new Review();
createReviewVariables.review.stars = 5;
createReviewVariables.review.commentary = 'This is a great movie!';
GraphQLQuery qry = new GraphQLQuery(node, createReviewVariables);
String payload = JSON.serialize(qry);
System.assertEquals(
'mutation CreateReviewForEpisode($ep:Episode!, $review:ReviewInput!){ createReview(episode:$ep, review:$review){ stars commentary } }',
qry.query.replace('\n', ' ').trim()
'{"variables":{"review":{"stars":5,"commentary":"This is a great movie!"},"ep":"JEDI"},"query":"mutation CreateReviewForEpisode($ep:Episode!, $review:ReviewInput!){\\ncreateReview(episode:$ep, review:$review){\\nstars\\ncommentary\\n}\\n}\\n"}',
payload
);
}

/* DTO for testOperation mutation test */
public class CreateReviewForEpisode
{
public String ep { get; set; }
public Review review { get; set; }
}

private class TestVariables {
public String foo;
public Decimal bar;
public class Review
{
public Integer stars { get; set; }
public String commentary { get; set; }
}

}

0 comments on commit 4fd6d33

Please sign in to comment.