diff --git a/README.md b/README.md index 35eaab3..845c427 100755 --- a/README.md +++ b/README.md @@ -26,31 +26,23 @@ a simple but powerful graphQL query builder ### If this was helpful, [★ it on github](https://github.com/codemeasandwich/graphql-query-builder) *tested on [**NodeJS**](https://nodejs.org) and [**Webpack**](https://webpack.github.io)* - - -## [Demo / Sandbox](https://tonicdev.com/codemeasandwich/57a0727c80254315001cb366) :thumbsup: - -# Install - -`npm install graphql-query-builder` - -# Api +## API ``` js -const Query = require('graphql-query-builder'); + const {Query, Mutation, Nested} = require('graphql-query-builder'); ``` ### constructor -query/mutator you wish to use, and an alias or filter arguments. +Query or Mutator you wish to use, and an alias or filter arguments. -| Argument (**one** to **two**) | Description +| Argument | Description |--- |--- | String | the name of the query function -| * String / Object | (**optional**) This can be an `alias` or `filter` values +| String or Object | (**optional**) This can be an `alias` or `filter` values ``` js -let profilePicture = new Query("profilePicture",{size : 50}); -``` + const profilePicture = new Query('profilePicture', {size: 50}); +``` ### setAlias set an alias for this result. @@ -60,8 +52,8 @@ set an alias for this result. | String | The alias for this result ``` js -profilePicture.setAlias("MyPic"); -``` + profilePicture.setAlias('MyPic'); +``` ### filter the parameters to run the query against. @@ -71,126 +63,133 @@ the parameters to run the query against. | Object | An object mapping attribute to values ``` js -profilePicture.filter({ height : 200, width : 200}); -``` + profilePicture.filter({ height: 200, width: 200}); +``` -### find +### select outlines the properties you wish to be returned from the query. -| Argument (**one** to **many**) | Description +| Argument | Description |--- |--- -| String or Object | representing each attribute you want Returned -| ... | *same as above* +| String or Object or Array | representing each attribute you want Returned -``` js - profilePicture.find( { link : "uri"}, "width", "height"); -``` +```javascript + profilePicture.select({link: 'uri'}, 'width', 'height'); +``` ### toString return to the formatted query string -``` js - // A (ES6) - `${profilePicture}`; - // B - profilePicture+''; - // C +```javascript profilePicture.toString(); -``` +``` + +## Examples -## run samples +### Nested Query Example -``` bash -node example/simple.js +```javascript + const profilePicture = new Nested('profilePicture', {size: 50}); + profilePicture.select('uri', 'width', 'height'); + + const user = new Query('user', {id: 123}); + user.select(['id', {nickname: 'name'}, 'isViewerFriend', {image: profilePicture}]); + + /* + query { + user( id:123 ) { + id, + nickname: name, + isViewerFriend, + image: profilePicture( size: 50 ) { + uri, + width, + height + } + } + } + */ ``` -# Example - -``` js -var Query = require('graphql-query-builder'); - -// example of nesting Querys -let profilePicture = new Query("profilePicture",{size : 50}); - profilePicture.find( "uri", "width", "height"); - -let user = new Query("user",{id : 123}); - user.find(["id", {"nickname":"name"}, "isViewerFriend", {"image":profilePicture}]) - - console.log(user) - /* - user( id:123 ) { - id, - nickname : name, - isViewerFriend, - - image : profilePicture( size:50 ) { - uri, - width, - height +### Mutation Example + +```javascript + const MessageRequest = { + type: 'chat', + message: 'yoyo', + user:{ + name: 'bob', + screen:{ + height: 1080, + width: 1920 + } + }, + friends: [ + {id: 1, name: 'ann'}, + {id: 2, name: 'tom'} + ] + }; + + const MessageQuery = new Mutation('Message', 'myPost'); + MessageQuery.filter(MessageRequest); + MessageQuery.select({messageId: 'id'}, {postedTime: 'createTime' }); + + /* + mutation { + myPost:Message( + type: 'chat', + message: 'yoyo', + user: { + name:'bob', + screen: { + height:1080, + width:1920 + } + }, + friends: [{id: 1, name: 'ann'},{id: 2, name: 'tom'}] + ) + { + messageId: id, + postedTime: createTime + } } - } - */ - -// And another example - -let MessageRequest = { type:"chat", message:"yoyo", - user:{ - name:"bob", - screen:{ - height:1080, - width:1920 - } - }, - friends:[ - {id:1,name:"ann"}, - {id:2,name:"tom"} - ] - }; - -let MessageQuery = new Query("Message","myPost"); - MessageQuery.filter(MessageRequest); - MessageQuery.find({ messageId : "id"}, {postedTime : "createTime" }); - - console.log(MessageQuery); - - /* - myPost:Message( type:"chat", - message:"yoyo", - user:{name:"bob",screen:{height:1080,width:1920}}, - friends:[{id:1,name:"ann"},{id:2,name:"tom"}]) - { - messageId : id, - postedTime : createTime + */ +``` + +### Nested select Query + +```javascript + const user = new Query('user'); + user.select([{profilePicture: ['uri', 'width', 'height']}]); + + /* + query { + user { + profilePicture { + uri, + width, + height } - */ - - // Simple nesting - - let user = new Query("user"); - user.find([{"profilePicture":["uri", "width", "height"]}]) - - /* - user { - profilePicture { - uri, - width, - height - } - } - */ - - // Simple nesting with rename - - let user = new Query("user"); - user.find([{"image":{"profilePicture":["uri", "width", "height"]}}]) - - /* - user { - image : profilePicture { - uri, - width, - height - } - } - */ + } + } + */ +``` + +### Nested select query with rename + +```javascript + const user = new Query('user'); + user.select([{image: {profilePicture: ['uri', 'width', 'height']}}]); + + /* + query { + user { + image: profilePicture { + uri, + width, + height + } + } + } + */ ``` diff --git a/example/simple.js b/example/simple.js index 5319f24..96c4643 100755 --- a/example/simple.js +++ b/example/simple.js @@ -1,50 +1,70 @@ -var Query = require('../'); - +const { + Query, + Nested +} = require('../'); /* -{ - user( id:3500401 ) { - id, - nickname : name, - isViewerFriend, - - profilePicture( size:50 ) { + EXAMPLE 1 + query { + user( id: 3500401 ) { + id, + nickname: name, + isViewerFriend, + profilePicture( size: 50 ) { uri, width, height + } } } -} */ -let profilePicture = new Query("profilePicture",{size : 50}); - profilePicture.find( "uri", "width", "height"); -let user = new Query("user",{id : 3500401}); - user.find(["id", {"nickname":"name"}, "isViewerFriend", {"image":profilePicture}]); +const profilePicture = new Query('profilePicture', { + size: 50 +}); +profilePicture.select('uri', 'width', 'height'); +const user = new Query('user', { + id: 3500401 +}); +user.select(['id', { + nickname: 'name' +}, 'isViewerFriend', { + image: profilePicture +}]); - logger.log("user",user+""); -/* +console.log('user', user + ''); -query FetchLeeAndSam { - lee: user(id: "1") { - name - } - sam: user(id: "2") { - name +/* + EXAMPLE 2 + query { + FetchLeeAndSam { + lee: user(id: '1') { + name + } + sam: user(id: '2') { + name + } + } } -} */ -let FetchLeeAndSam = new Query("FetchLeeAndSam"); - -let lee = new Query("user",{id : '1'}); - lee.setAlias('lee'); - lee.find({name:true}); - logger.log("lee",lee.toString()); - -let sam = new Query("user","sam"); - sam.filter({id : '2'}); - sam.find("name"); - logger.log("sam",sam+""); - - console.log(FetchLeeAndSam.find(lee,sam)+""); +const FetchLeeAndSam = new Query('FetchLeeAndSam'); + +const lee = new Nested('user', { + id: '1' +}); +lee.setAlias('lee'); +lee.select({ + name: true +}); + +console.log('lee', lee.toString()); + +const sam = new Nested('user', 'sam'); +sam.filter({ + id: '2' +}); +sam.select('name'); +console.log('sam', sam + ''); + +console.log(FetchLeeAndSam.select(lee, sam) + ''); diff --git a/index.js b/index.js index 78e960a..ebcdce2 100755 --- a/index.js +++ b/index.js @@ -1,147 +1,179 @@ -"use strict"; - -//===================================================== -//============================ parce properties to find -//===================================================== - -function parceFind(_levelA) { - -//+++++++++++++++++++++++++++++++++++ work over Array -//++++++++++++++++++++++++++++++++++++++++++++++++++++ - - let propsA = _levelA.map(function(currentValue, index) { - - let itemX = _levelA[index]; - - if( itemX instanceof Query){ - return itemX.toString(); - } else if ( ! Array.isArray(itemX) && "object" === typeof itemX ) { - let propsA = Object.keys(itemX); - if ( 1 !== propsA.length) { - throw new RangeError("Alias objects should only have one value. was passed: "+JSON.stringify(itemX)); +/* eslint-disable require-jsdoc, yoda, no-use-before-define */ +const MSG = { + INVALID_SECOND_ARG: 'Second argument to should be an alias name(String) or filter arguments(Object). Instead: ', + UNDEFINED_SECOND_ARG: 'You have passed undefined as Second argument to \'Query\'', + INVALID_ALIAS: 'Alias objects should only have one value. Instead: ', + MISSING_RETURN_PROPERTIES: 'return properties are not defined. use the \'select\' function to defined them', + INVALID_SELECT: 'Cannot handle select value of ', + FALSY_SELECT: 'select value can not be >>falsy<<' +}; + +class Query { + constructor(field, fieldAlias_OR_args) { + + this.field = field; + this.args = []; + + if ('string' === typeof fieldAlias_OR_args) { + this.fieldAlias = fieldAlias_OR_args; + } else if ('object' === typeof fieldAlias_OR_args) { + this.filter(fieldAlias_OR_args); + } else if (undefined !== fieldAlias_OR_args) { + throw new TypeError(MSG.INVALID_SECOND_ARG + fieldAlias_OR_args); + } + } + + /** + * Provide arguments to the Query or Mutation + * @param {object} args + * @return {Query} + */ + filter(args) { + + Object.keys(args).forEach((filterKey) => { + if ('function' === typeof args[filterKey]) { + return; } - let propS = propsA[0]; - let item = itemX[propS]; - // contributor: https://github.com/charlierudolph/graphql-query-builder/commit/878328e857e92d140f5ba6f7cfe07837620ec490 - if (Array.isArray(item)) { - return new Query(propS).find(item) + const filterValue = this._getGraphQLValue(args[filterKey]); + if ('{}' === filterValue) { + return; } - return `${propS} : ${item} `; - } else if ( "string" === typeof itemX ) { - return itemX; + this.args.push(`${filterKey}:${filterValue}`); + }); + + return this; + } + + /** + * get GraphQL Value + * @param {string|Array|object} value + * @return {string} + * @private + */ + _getGraphQLValue(value) { + let graphQLValue; + if ('string' === typeof value) { + graphQLValue = JSON.stringify(value); + } else if (Array.isArray(value)) { + graphQLValue = value.map((item) => { + return this._getGraphQLValue(item); + }).join(); + graphQLValue = `[${graphQLValue}]`; + } else if ('object' === typeof value) { + graphQLValue = this._objectToString(value); } else { - throw new RangeError("cannot handle Find value of "+itemX); + graphQLValue = value; } - }); - - return propsA.join(","); -} + return graphQLValue; + } -//===================================================== -//=================================== get GraphQL Value -//===================================================== + /** + * @param {object} obj + * @return {string} + * @private + */ + _objectToString(obj) { -function getGraphQLValue(value) { - if ("string" === typeof value) { - value = JSON.stringify(value); - } else if (Array.isArray(value)) { - value = value.map(item => { - return getGraphQLValue(item); - }).join(); - value = `[${value}]`; - } else if ("object" === typeof value) { - /*if (value.toSource) - value = value.toSource().slice(2,-2); - else*/ - value = objectToString(value); - //console.error("No toSource!!",value); - } - return value; -} + const sourceA = []; -function objectToString(obj) { - - let sourceA = []; - - for(let prop in obj){ - if ("function" === typeof obj[prop]) { - continue; + Object.keys(obj).forEach((key) => { + if ('function' === typeof obj[key]) { + return; + } + sourceA.push(`${key}:${this._getGraphQLValue(obj[key])}`); + }); + return `{${sourceA.join()}}`; } - // if ("object" === typeof obj[prop]) { - sourceA.push(`${prop}:${getGraphQLValue(obj[prop])}`); - // } else { - // sourceA.push(`${prop}:${obj[prop]}`); - // } - } - return `{${sourceA.join()}}`; -} + setAlias(_fieldAlias) { + this.fieldAlias = _fieldAlias; + return this; + } + /** + * Select the values that you would like returned in the response from the server + * @param {Array} selectionFields + * @return {Query} + */ + select(selectionFields) { + if (!selectionFields) { + throw new TypeError(MSG.FALSY_SELECT); + } + // If its a string, then it may have other values + // else it should be an Object or Array of mapped values + const selectionArray = Array.isArray(selectionFields) ? selectionFields : Array.from(arguments); + this.selectionFields = this._parseSelection(selectionArray); + return this; + } + find(selectionFields) { + return this.select(selectionFields); + } -//===================================================== -//========================================= Query Class -//===================================================== + /** + * parse properties to find + * @param {Array} selectionFields + * @return {string} + * @private + */ + _parseSelection(selectionFields) { -function Query(_fnNameS, _aliasS_OR_Filter){ - - this.fnNameS = _fnNameS; - this.headA = []; - - this.filter = (filtersO) => { - - for(let propS in filtersO){ - if ("function" === typeof filtersO[propS]) { - continue; + const selection = selectionFields.map(function(returnProperty) { + if (returnProperty instanceof Query) { + return returnProperty.toString(); + } else if (!Array.isArray(returnProperty) && 'object' === typeof returnProperty) { + const filterKeysA = Object.keys(returnProperty); + if (1 !== filterKeysA.length) { + throw new RangeError(MSG.INVALID_ALIAS + JSON.stringify(returnProperty)); + } + const filterKey = filterKeysA[0]; + const item = returnProperty[filterKey]; + if (Array.isArray(item)) { + return new Nested(filterKey).select(item); + } + return `${filterKey} : ${item} `; + } else if ('string' === typeof returnProperty) { + return returnProperty; + } else { + throw new RangeError(MSG.INVALID_SELECT + returnProperty); } - let val = getGraphQLValue(filtersO[propS]); - if ("{}" === val) { - continue; - } - this.headA.push( `${propS}:${val}` ); - } - return this; - }; - - if ("string" === typeof _aliasS_OR_Filter) { - this.aliasS = _aliasS_OR_Filter; - } else if ("object" === typeof _aliasS_OR_Filter) { - this.filter(_aliasS_OR_Filter); - } else if (undefined === _aliasS_OR_Filter && 2 === arguments.length){ - throw new TypeError("You have passed undefined as Second argument to 'Query'"); - } else if (undefined !== _aliasS_OR_Filter){ - throw new TypeError("Second argument to 'Query' should be an alias name(String) or filter arguments(Object). was passed "+_aliasS_OR_Filter); + }); + + return selection.join(','); } - this.setAlias = (_aliasS) =>{ - this.aliasS = _aliasS; - return this; - }; - - this.find = function(findA) { // THIS NEED TO BE A "FUNCTION" to scope 'arguments' - if( ! findA){ - throw new TypeError("find value can not be >>falsy<<"); + /** + * @return {string} + * @private + */ + _baseToString() { + const fieldAlias = this.fieldAlias ? this.fieldAlias + ':' : ''; + const args = 0 < this.args.length ? '(' + this.args.join(',') + ')' : ''; + const selection = this.selectionFields ? '{' + this.selectionFields + '}' : ''; + return `${fieldAlias} ${this.field} ${args} ${selection}`; + } + + toString() { + if (undefined === this.selectionFields) { + throw new ReferenceError(MSG.MISSING_RETURN_PROPERTIES); } - // if its a string.. it may have other values - // else it sould be an Object or Array of maped values - this.bodyS = parceFind((Array.isArray(findA)) ? findA : Array.from(arguments)); - return this; - }; + return `query {${this._baseToString()}}`; + } } -//===================================================== -//===================================== Query prototype -//===================================================== - -Query.prototype = { - - toString : function(){ - if (undefined === this.bodyS) { - throw new ReferenceError("return properties are not defined. use the 'find' function to defined them"); - } - - return `${ (this.aliasS) ? (this.aliasS + ":") : "" } ${this.fnNameS } ${ (0 < this.headA.length)?"("+this.headA.join(",")+")":"" } { ${ this.bodyS } }`; +class Mutation extends Query { + toString() { + return `mutation {${this._baseToString()}}`; } -}; +} +class Nested extends Query { + toString() { + return this._baseToString(); + } +} -module.exports = Query; +module.exports = { + Query, + Mutation, + Nested +}; diff --git a/test.js b/test.js index 42e3bda..91b0f54 100644 --- a/test.js +++ b/test.js @@ -1,200 +1,250 @@ -"use strict"; -var expect = require('chai').expect; -var Query = require('./index'); +/* eslint-disable require-jsdoc, max-lines-per-function */ +'use strict'; +const expect = require('chai').expect; +const { + Query, + Nested +} = require('./index'); function removeSpaces(textS) { - return `${textS}`.replace(/\s+/g, ''); + return `${textS}`.replace(/\s+/g, ''); } -describe("graphql query builder", function() { //log the function - - it('should accept a single find value', function(){ - let expeted = `user{age}`; - let user = new Query("user").find("age"); - - expect(removeSpaces(expeted)).to.equal(removeSpaces(user)); - }); - - it('should create a Query with function name & alia', function(){ - - let expeted = `sam : user{name}`; - let user = new Query("user","sam").find("name"); - - expect(removeSpaces(expeted)).to.equal(removeSpaces(user)); - }); - - it('should create a Query with function name & input', function(){ - - let expeted = `user(id:12345){name}`; - let user = new Query("user",{id : 12345}).find("name"); - - expect(removeSpaces(expeted)).to.equal(removeSpaces(user)); - }); - - it('should create a Query with function name & input(s)', function(){ - - let expeted = `user(id:12345, age:34){name}`; - let user = new Query("user",{id : 12345, age:34}).find("name"); - - expect(removeSpaces(expeted)).to.equal(removeSpaces(user)); - }); - - it('should accept a single find value with alia', function(){ - let expeted = `user{nickname:name}`; - let user = new Query("user").find({nickname:"name"}); - - expect(removeSpaces(expeted)).to.equal(removeSpaces(user)); - }); - - it('should accept a multiple find values', function(){ - let expeted = `user{firstname, lastname}`; - let user = new Query("user").find("firstname","lastname") - - expect(removeSpaces(expeted)).to.equal(removeSpaces(user)); - }); - - it('should accept an array find values', function(){ - let expeted = `user{firstname, lastname}`; - let user = new Query("user").find(["firstname","lastname"]); - - expect(removeSpaces(expeted)).to.equal(removeSpaces(user)); - }); - - it('should work with nesting Querys', function(){ - - let expeted = `user( id:12345 ) { - id, nickname : name, isViewerFriend, - image : profilePicture( size:50 ) { - uri, width, height } }`; - - let profilePicture = new Query("profilePicture",{size : 50}); - profilePicture.find( "uri", "width", "height"); - - let user = new Query("user",{id : 12345}); - user.find(["id", {"nickname":"name"}, "isViewerFriend", {"image":profilePicture}]); - - expect(removeSpaces(expeted)).to.equal(removeSpaces(user)); - }); - - it('should work with simple nesting Querys', function(){ - - let expeted = `user { profilePicture { uri, width, height } }` - - let user = new Query("user"); - user.find({"profilePicture": ['uri', 'width', 'height']}); - - expect(removeSpaces(expeted)).to.equal(removeSpaces(user)); - }); - - it('should be able to group Querys', function(){ - - let expeted = `FetchLeeAndSam { lee: user(id: "1") { name }, - sam: user(id: "2") { name } }`; - - let FetchLeeAndSam = new Query("FetchLeeAndSam"); - - let lee = new Query("user",{id : '1'}); - lee.setAlias('lee'); - lee.find(["name"]); - - let sam = new Query("user","sam"); - sam.filter({id : '2'}); - sam.find("name"); - - FetchLeeAndSam.find(lee,sam); - - expect(removeSpaces(expeted)).to.equal(removeSpaces(FetchLeeAndSam)); - }); - - it('should work with nasted objects and lists', function(){ - - let expeted =`myPost:Message(type:"chat",message:"yoyo", +describe('graphql query builder', function() { // log the function + it('should accept a single find value', function() { + const expected = `query{user{age}}`; + const user = new Query('user').select('age'); + + expect(removeSpaces(expected)).to.equal(removeSpaces(user)); + }); + + it('should create a Query with function name & alias', function() { + + const expected = `query{sam : user{name}}`; + const user = new Query('user', 'sam').select('name'); + + expect(removeSpaces(expected)).to.equal(removeSpaces(user)); + }); + + it('should create a Query with function name & input', function() { + + const expected = `query{user(id:12345){name}}`; + const user = new Query('user', { + id: 12345 + }).select('name'); + + expect(removeSpaces(expected)).to.equal(removeSpaces(user)); + }); + + it('should create a Query with function name & input(s)', function() { + + const expected = `query{user(id:12345, age:34){name}}`; + const user = new Query('user', { + id: 12345, + age: 34 + }).select('name'); + + expect(removeSpaces(expected)).to.equal(removeSpaces(user)); + }); + + it('should accept a single find value with alia', function() { + const expected = `query{user{nickname:name}}`; + const user = new Query('user').select({ + nickname: 'name' + }); + + expect(removeSpaces(expected)).to.equal(removeSpaces(user)); + }); + + it('should accept a multiple find values', function() { + const expected = `query{user{firstname, lastname}}`; + const user = new Query('user').select('firstname', 'lastname'); + + expect(removeSpaces(expected)).to.equal(removeSpaces(user)); + }); + + it('should accept an array find values', function() { + const expected = `query{user{firstname, lastname}}`; + const user = new Query('user').select(['firstname', 'lastname']); + + expect(removeSpaces(expected)).to.equal(removeSpaces(user)); + }); + + it('should work with nesting Querys', function() { + + const expected = `query{user( id:12345 ) { + id, nickname : name, isViewerFriend, + image : profilePicture( size:50 ) { + uri, width, height } }}`; + + const profilePicture = new Nested('profilePicture', { + size: 50 + }); + profilePicture.select('uri', 'width', 'height'); + + const user = new Query('user', { + id: 12345 + }); + user.select(['id', { + 'nickname': 'name' + }, 'isViewerFriend', { + 'image': profilePicture + }]); + + expect(removeSpaces(expected)).to.equal(removeSpaces(user)); + }); + + it('should work with simple nesting Querys', function() { + + const expected = `query{user { profilePicture { uri, width, height } }}`; + + const user = new Query('user'); + user.select({ + 'profilePicture': ['uri', 'width', 'height'] + }); + + expect(removeSpaces(expected)).to.equal(removeSpaces(user)); + }); + + it('should be able to group Querys', function() { + + const expected = `query{FetchLeeAndSam { lee: user(id: "1") { name }, + sam: user(id: "2") { name } }}`; + + const FetchLeeAndSam = new Query('FetchLeeAndSam'); + + const lee = new Nested('user', { + id: '1' + }); + lee.setAlias('lee'); + lee.select(['name']); + + const sam = new Nested('user', 'sam'); + sam.filter({ + id: '2' + }); + sam.select('name'); + + FetchLeeAndSam.select(lee, sam); + + expect(removeSpaces(expected)).to.equal(removeSpaces(FetchLeeAndSam)); + }); + + it('should work with nasted objects and lists', function() { + + const expected = `query{myPost:Message(type:"chat",message:"yoyo", user:{name:"bob",screen:{height:1080,width:1920}}, friends:[{id:1,name:"ann"},{id:2,name:"tom"}]) { - messageId : id, postedTime : createTime }`; - - let MessageRequest = { type:"chat", - message:"yoyo", - user:{ name:"bob", - screen:{ height:1080, width:1920 } }, - friends:[ {id:1,name:"ann"}, {id:2,name:"tom"} ] - }; - - let MessageQuery = new Query("Message","myPost"); - MessageQuery.filter(MessageRequest); - MessageQuery.find({ messageId : "id"}, {postedTime : "createTime" }); - - expect(removeSpaces(expeted)).to.equal(removeSpaces(MessageQuery)); - - }); - - it('should work with objects that have help functions(will skip function name)', function(){ - - let expeted ='inventory(toy:"jack in the box") { id }'; - - let ChildsToy = { toy:"jack in the box", getState:function(){ } }; - - ChildsToy.getState();//for istanbul(coverage) to say all fn was called - - let ItemQuery = new Query("inventory",ChildsToy); - ItemQuery.find("id"); - - expect(removeSpaces(expeted)).to.equal(removeSpaces(ItemQuery)); - - }); - - it('should work with nasted objects that have help functions(will skip function name)', function(){ - - let expeted ='inventory(toy:"jack in the box") { id }'; - - let ChildsToy = { toy:"jack in the box", utils: { getState:function(){ } } }; - - ChildsToy.utils.getState();//for istanbul(coverage) to say all fn was called - - let ItemQuery = new Query("inventory",ChildsToy); - ItemQuery.find("id"); - - expect(removeSpaces(expeted)).to.equal(removeSpaces(ItemQuery)); - - }); - - it('should skip empty objects in filter/args', function(){ - - let expeted ='inventory(toy:"jack in the box") { id }'; - - let ChildsToy = { toy:"jack in the box", utils: { } }; - - let ItemQuery = new Query("inventory",ChildsToy); - ItemQuery.find("id"); - - expect(removeSpaces(expeted)).to.equal(removeSpaces(ItemQuery)); - }); - - it('should throw Error if find input items have zero props', function(){ - expect(() => new Query("x").find({})).to.throw(Error); - }); - - it('should throw Error if find input items have multiple props', function(){ - expect(() => new Query("x").find({a:"z",b:"y"})).to.throw(Error); - }); - - it('should throw Error if find is undefined', function(){ - expect(() => new Query("x").find()).to.throw(Error); - }); - - it('should throw Error if no find values have been set', function(){ - expect(() => `${new Query("x")}`).to.throw(Error); - }); - - it('should throw Error if find is not valid', function(){ - expect(() => new Query("x").find(123)).to.throw(Error); - }); - - it('should throw Error if you accidentally pass an undefined', function(){ - expect(() => new Query("x",undefined)).to.throw(Error); - }); - - it('should throw Error it is not an input object for alias', function(){ - expect(() => new Query("x",true)).to.throw(Error); - }); -}); \ No newline at end of file + messageId : id, postedTime : createTime }}`; + + const MessageRequest = { + type: 'chat', + message: 'yoyo', + user: { + name: 'bob', + screen: { + height: 1080, + width: 1920 + } + }, + friends: [{ + id: 1, + name: 'ann' + }, { + id: 2, + name: 'tom' + }] + }; + + const MessageQuery = new Query('Message', 'myPost'); + MessageQuery.filter(MessageRequest); + MessageQuery.select({ + messageId: 'id' + }, { + postedTime: 'createTime' + }); + + expect(removeSpaces(expected)).to.equal(removeSpaces(MessageQuery)); + + }); + + it('should work with objects that have help functions(will skip function name)', function() { + + const expected = 'query{inventory(toy:"jack in the box") { id }}'; + + const ChildsToy = { + toy: 'jack in the box', + getState: function() {} + }; + + ChildsToy.getState(); // for istanbul(coverage) to say all fn was called + + const ItemQuery = new Query('inventory', ChildsToy); + ItemQuery.select('id'); + + expect(removeSpaces(expected)).to.equal(removeSpaces(ItemQuery)); + + }); + + it('should work with nasted objects that have help functions(will skip function name)', function() { + + const expected = 'query{inventory(toy:"jack in the box") { id }}'; + + const ChildsToy = { + toy: 'jack in the box', + utils: { + getState: function() {} + } + }; + + ChildsToy.utils.getState(); // for istanbul(coverage) to say all fn was called + + const ItemQuery = new Query('inventory', ChildsToy); + ItemQuery.select('id'); + + expect(removeSpaces(expected)).to.equal(removeSpaces(ItemQuery)); + + }); + + it('should skip empty objects in filter/args', function() { + + const expected = 'query{inventory(toy:"jack in the box") { id }}'; + + const ChildsToy = { + toy: 'jack in the box', + utils: {} + }; + + const ItemQuery = new Query('inventory', ChildsToy); + ItemQuery.select('id'); + + expect(removeSpaces(expected)).to.equal(removeSpaces(ItemQuery)); + }); + + it('should throw Error if find input items have zero props', function() { + expect(() => new Query('x').select({})).to.throw(Error); + }); + + it('should throw Error if find input items have multiple props', function() { + expect(() => new Query('x').select({ + a: 'z', + b: 'y' + })).to.throw(Error); + }); + + it('should throw Error if find is undefined', function() { + expect(() => new Query('x').select()).to.throw(Error); + }); + + it('should throw Error if no find values have been set', function() { + expect(() => `${new Query('x')}`).to.throw(Error); + }); + + it('should throw Error if find is not valid', function() { + expect(() => new Query('x').select(123)).to.throw(Error); + }); + + it('should throw Error it is not an input object for alias', function() { + expect(() => new Query('x', true)).to.throw(Error); + }); +});