import { Resolver , schemaComposer , ObjectTypeComposer } from 'graphql-compose' ; import { Query } from 'mongoose' ; import { UserModel , IUser } from '../../__mocks__/userModel' ; import { connection , prepareCursorQuery } from '../connection' ; import { findMany } from '../findMany' ; import { count } from '../count' ; import { convertModelToGraphQL } from '../../fieldsConverter' ; import { ExtendedResolveParams } from '..' ; jest . mock ( '../findMany' , ( ) => ( { findMany : jest . fn ( ( ... args ) => jest . requireActual ( '../findMany' ) . findMany ( ... args ) ) , } ) ) ; jest . mock ( '../count' , ( ) => ( { count : jest . fn ( ( ... args ) => jest . requireActual ( '../count' ) . count ( ... args ) ) , } ) ) ; beforeAll ( ( ) => UserModel . base . createConnection ( ) ) ; afterAll ( ( ) => UserModel . base . disconnect ( ) ) ; describe ( 'connection() resolver' , ( ) => { describe ( 'prepareCursorQuery()' , ( ) => { let rawQuery ; describe ( 'single index' , ( ) => { const cursorData = { a : 10 } ; const indexKeys = Object . keys ( cursorData ) ; it ( 'asc order' , ( ) => { const indexData = { a : 1 } ; rawQuery = { } ; prepareCursorQuery ( rawQuery , cursorData , indexKeys , indexData , '$lt' , '$gt' ) ; expect ( rawQuery ) . toEqual ( { a : { $lt : 10 } } ) ; rawQuery = { } ; prepareCursorQuery ( rawQuery , cursorData , indexKeys , indexData , '$gt' , '$lt' ) ; expect ( rawQuery ) . toEqual ( { a : { $gt : 10 } } ) ; } ) ; it ( 'desc order' , ( ) => { const indexData = { a : - 1 } ; rawQuery = { } ; prepareCursorQuery ( rawQuery , cursorData , indexKeys , indexData , '$lt' , '$gt' ) ; expect ( rawQuery ) . toEqual ( { a : { $gt : 10 } } ) ; rawQuery = { } ; prepareCursorQuery ( rawQuery , cursorData , indexKeys , indexData , '$gt' , '$lt' ) ; expect ( rawQuery ) . toEqual ( { a : { $lt : 10 } } ) ; } ) ; } ) ; describe ( 'compound index' , ( ) => { const cursorData = { a : 10 , b : 100 , c : 1000 } ; const indexKeys = Object . keys ( cursorData ) ; it ( 'asc order' , ( ) => { const indexData = { a : 1 , b : - 1 , c : 1 } ; rawQuery = { } ; prepareCursorQuery ( rawQuery , cursorData , indexKeys , indexData , '$lt' , '$gt' ) ; expect ( rawQuery ) . toEqual ( { $or : [ { a : 10 , b : 100 , c : { $lt : 1000 } } , { a : 10 , b : { $gt : 100 } } , { a : { $lt : 10 } } , ] , } ) ; rawQuery = { } ; prepareCursorQuery ( rawQuery , cursorData , indexKeys , indexData , '$gt' , '$lt' ) ; expect ( rawQuery ) . toEqual ( { $or : [ { a : 10 , b : 100 , c : { $gt : 1000 } } , { a : 10 , b : { $lt : 100 } } , { a : { $gt : 10 } } , ] , } ) ; } ) ; it ( 'desc order' , ( ) => { const indexData = { a : - 1 , b : 1 , c : - 1 } ; rawQuery = { } ; prepareCursorQuery ( rawQuery , cursorData , indexKeys , indexData , '$lt' , '$gt' ) ; expect ( rawQuery ) . toEqual ( { $or : [ { a : 10 , b : 100 , c : { $gt : 1000 } } , { a : 10 , b : { $lt : 100 } } , { a : { $gt : 10 } } , ] , } ) ; rawQuery = { } ; prepareCursorQuery ( rawQuery , cursorData , indexKeys , indexData , '$gt' , '$lt' ) ; expect ( rawQuery ) . toEqual ( { $or : [ { a : 10 , b : 100 , c : { $lt : 1000 } } , { a : 10 , b : { $gt : 100 } } , { a : { $lt : 10 } } , ] , } ) ; } ) ; } ) ; } ) ; describe ( 'connection() -> ' , ( ) => { let UserTC ; beforeEach ( ( ) => { schemaComposer . clear ( ) ; UserTC = convertModelToGraphQL ( UserModel , 'User' , schemaComposer ) ; } ) ; let user1 ; let user2 ; beforeEach ( async ( ) => { await UserModel . deleteMany ( { } ) ; user1 = new UserModel ( { name : 'userName1' , skills : [ 'js' , 'ruby' , 'php' , 'python' ] , gender : 'male' , relocation : true , contacts : { email : 'mail' } , } ) ; user2 = new UserModel ( { name : 'userName2' , skills : [ 'go' , 'erlang' ] , gender : 'female' , relocation : false , contacts : { email : 'mail' } , } ) ; await user1 . save ( ) ; await user2 . save ( ) ; } ) ; it ( 'should return Resolver object with default name' , ( ) => { const resolver = connection ( UserModel , UserTC ) ; if ( ! resolver ) throw new Error ( 'Connection resolver is undefined' ) ; expect ( resolver ) . toBeInstanceOf ( Resolver ) ; expect ( resolver . getNestedName ( ) ) . toEqual ( 'connection' ) ; } ) ; it ( 'Resolver object should have `filter` arg' , ( ) => { const resolver = connection ( UserModel , UserTC ) ; if ( ! resolver ) throw new Error ( 'Connection resolver is undefined' ) ; expect ( resolver . hasArg ( 'filter' ) ) . toBe ( true ) ; } ) ; it ( 'Resolver object should have `sort` arg' , ( ) => { const resolver = connection ( UserModel , UserTC ) ; if ( ! resolver ) throw new Error ( 'Connection resolver is undefined' ) ; expect ( resolver . hasArg ( 'sort' ) ) . toBe ( true ) ; } ) ; it ( 'Resolver object should have `connection args' , ( ) => { const resolver = connection ( UserModel , UserTC ) ; if ( ! resolver ) throw new Error ( 'Connection resolver is undefined' ) ; expect ( resolver . hasArg ( 'first' ) ) . toBe ( true ) ; expect ( resolver . hasArg ( 'last' ) ) . toBe ( true ) ; expect ( resolver . hasArg ( 'before' ) ) . toBe ( true ) ; expect ( resolver . hasArg ( 'after' ) ) . toBe ( true ) ; } ) ; it ( 'should create custom edge type' , ( ) => { const resolver = connection ( UserModel , UserTC , { edgeTypeName : 'CustomEdge' , } as any ) ; if ( ! resolver ) throw new Error ( 'Connection resolver is undefined' ) ; expect ( schemaComposer . has ( 'CustomEdge' ) ) . toBe ( true ) ; } ) ; describe ( 'Resolver.resolve():Promise' , ( ) => { it ( 'should be fulfilled Promise' , async ( ) => { const resolver = connection ( UserModel , UserTC ) ; if ( ! resolver ) throw new Error ( 'Connection resolver is undefined' ) ; const result = resolver . resolve ( { args : { first : 20 } } ) ; await expect ( result ) . resolves . toBeDefined ( ) ; } ) ; it ( 'should return array of documents in `edges`' , async ( ) => { const resolver = connection ( UserModel , UserTC ) ; if ( ! resolver ) throw new Error ( 'Connection resolver is undefined' ) ; const result = await resolver . resolve ( { args : { first : 20 } } ) ; expect ( result . edges ) . toBeInstanceOf ( Array ) ; expect ( result . edges ) . toHaveLength ( 2 ) ; expect ( result . edges . map ( ( d ) => d . node . name ) ) . toEqual ( expect . arrayContaining ( [ user1 . name , user2 . name ] ) ) ; } ) ; it ( 'should limit records' , async ( ) => { const resolver = connection ( UserModel , UserTC ) ; if ( ! resolver ) throw new Error ( 'Connection resolver is undefined' ) ; const result = await resolver . resolve ( { args : { first : 1 } } ) ; expect ( result . edges ) . toBeInstanceOf ( Array ) ; expect ( result . edges ) . toHaveLength ( 1 ) ; } ) ; it ( 'should sort records' , async ( ) => { const resolver = connection ( UserModel , UserTC ) ; if ( ! resolver ) throw new Error ( 'Connection resolver is undefined' ) ; const result1 = await resolver . resolve ( { args : { sort : { _id : 1 } , first : 1 } , } ) ; const result2 = await resolver . resolve ( { args : { sort : { _id : - 1 } , first : 1 } , } ) ; expect ( `${ result1 . edges [ 0 ] . node . _id }` ) . not . toBe ( `${ result2 . edges [ 0 ] . node . _id }` ) ; } ) ; it ( 'should return mongoose documents' , async ( ) => { const resolver = connection ( UserModel , UserTC ) ; if ( ! resolver ) throw new Error ( 'Connection resolver is undefined' ) ; const result = await resolver . resolve ( { args : { first : 20 } } ) ; expect ( result . edges [ 0 ] . node ) . toBeInstanceOf ( UserModel ) ; expect ( result . edges [ 1 ] . node ) . toBeInstanceOf ( UserModel ) ; } ) ; it ( 'should call `beforeQuery` method with non-executed `query` as arg' , async ( ) => { expect . assertions ( 4 ) ; let extendedQuery ; const resolver = connection ( UserModel , UserTC ) ; const result = await resolver . resolve ( { args : { } , beforeQuery : ( query , rp ) => { expect ( query ) . toBeInstanceOf ( Query ) ; expect ( rp . model ) . toBe ( UserModel ) ; extendedQuery = query . where ( { _id : user1 . id } ) . limit ( 1989 ) ; return extendedQuery ; } , } ) ; expect ( result . edges ) . toHaveLength ( 1 ) ; expect ( result . edges [ 0 ] . node . _id . toString ( ) ) . toEqual ( user1 . id . toString ( ) ) ; } ) ; it ( 'should override result with `beforeQuery`' , async ( ) => { const resolver = connection ( UserModel , UserTC ) ; if ( ! resolver ) { throw new Error ( 'resolver is undefined' ) ; } const result = await resolver . resolve ( { args : { } , beforeQuery : ( query , rp ) => { expect ( query ) . toBeInstanceOf ( Query ) ; expect ( rp . model ) . toBe ( UserModel ) ; return [ { overrides : true } ] ; } , } ) ; expect ( result ) . toHaveProperty ( 'edges.0.node' , { overrides : true } ) ; } ) ; it ( 'should use internal resolver custom opts' , async ( ) => { schemaComposer . clear ( ) ; UserTC = convertModelToGraphQL ( UserModel , 'User' , schemaComposer ) ; const mockCountOpts = { suffix : 'ABC' } ; const mockFindManyOpts = { suffix : 'DEF' } ; const resolver = connection ( UserModel , UserTC , { countOpts : mockCountOpts , findManyOpts : mockFindManyOpts , } as any ) ; if ( ! resolver ) throw new Error ( 'Connection resolver is undefined' ) ; expect ( count ) . toHaveBeenCalledWith ( expect . anything ( ) , expect . anything ( ) , mockCountOpts ) ; expect ( findMany ) . toHaveBeenCalledWith ( expect . anything ( ) , expect . anything ( ) , mockFindManyOpts ) ; } ) ; } ) ; } ) ; } ) ;