import { ApolloClient } from 'apollo-client'; import gql from 'graphql-tag'; import { genie, getClient } from '../setupTests'; import { GraphQLScalarType } from 'graphql'; import { GraphQLGenie } from '../..'; let client: ApolloClient; beforeAll(async () => { client = getClient(); }); beforeEach(() => { client.cache['data'].data = {}; }); const testData = { users: [], posts: [], addresses: [], comments: [] }; const createUser = gql` mutation createUser($input: CreateUserMutationInput!) { createUser(input: $input) { data { id name age birthday email } clientMutationId } } `; const updateUser = gql` mutation updateUser($input: UpdateUserMutationInput!) { updateUser(input: $input ) { data { id name address { id city user { name } } } } } `; const createPost = gql` mutation createUser($input: CreatePostMutationInput!) { createPost(input: $input) { data { id title } clientMutationId } } `; describe('genie', () => { test('create - simple user', async () => { const $name = 'Corey J'; const $age = 30; const $birthday = '1988-02-23'; const $email = 'coreyj@example.com'; const user = await client.mutate({ mutation: createUser, variables: { input: { clientMutationId: 'create simple user', data: { name: $name, age: $age, birthday: $birthday, email: $email } } } }); testData.users.push(user.data.createUser.data); expect(user.data.createUser.clientMutationId).toBe('create simple user'); expect(user.data.createUser.data.name).toBe($name); expect(user.data.createUser.data.age).toBe($age); expect(user.data.createUser.data.birthday).toBe($birthday); expect(user.data.createUser.data.email).toBe($email); }); test('create - post on existing user', async () => { const $title = 'Genie is great'; const createPost = gql` mutation createPost($input: CreatePostMutationInput!) { createPost(input: $input) { data { id title author { id name email } } } } `; const result = await client.mutate({ mutation: createPost, variables: { input: { data: { title: $title, author: { connect: { id: testData.users[0].id } } } } } }); testData.posts.push(result.data.createPost.data); expect(result.data.createPost.data.title).toBe($title); expect(result.data.createPost.data.author.id).toBe(testData.users[0].id); expect(result.data.createPost.data.author.name).toBe(testData.users[0].name); }); test('find - make sure user also has post', async () => { const users = gql` query users($where: JSON) { users(where: $where) { id writtenSubmissions { id } } } `; const result = await client.query({ query: users, variables: { where: { match: { id: testData.users[0].id } } } }); expect(result.data['users'][0].writtenSubmissions[0].id).toBe(testData.posts[0].id); }); test('find singular - make sure user also has post', async () => { const user = gql` query user($id: ID){ user(id: $id) { id writtenSubmissions { id } } } `; const result = await client.query({ query: user, variables: { id: testData.users[0].id } }); expect(result.data['user'].id).toBe(testData.users[0].id); expect(result.data['user'].writtenSubmissions[0].id).toBe(testData.posts[0].id); }); test('create - post with new user', async () => { const $title = 'Genie is more than great'; const $authorName = 'Totally Real Person'; const $email = 'real@example.com'; const createPost = gql` mutation createPost($input: CreatePostMutationInput!) { createPost(input: $input) { data { id title author { id name email } } } } `; const result = await client.mutate({ mutation: createPost, variables: { input: { data: { title: $title, author: { create: { name: $authorName, email: $email } } } } } }); testData.posts.push(result.data.createPost.data); testData.users.push(result.data.createPost.data.author); expect(result.data.createPost.data.title).toBe($title); expect(result.data.createPost.data.author.id).toBeDefined(); expect(result.data.createPost.data.author.name).toBe($authorName); expect(result.data.createPost.data.author.email).toBe($email); }); test('create - simple address', async () => { const $city = 'Eau Claire'; const createAddress = gql` mutation createAddress($input: CreateAddressMutationInput!) { createAddress(input: $input) { data { id city } } } `; const result = await client.mutate({ mutation: createAddress, variables: { input: { data: { city: $city } } } }); testData.addresses.push(result.data.createAddress.data); expect(result.data.createAddress.data.city).toBe($city); }); test('set - set user address', async () => { const result = await client.mutate({ mutation: updateUser, variables: { input: { where: { id: testData.users[0].id }, data: { address: { connect: { id: testData.addresses[0].id } } } } } }); expect(result.data.updateUser.data.id).toBe(testData.users[0].id); expect(result.data.updateUser.data.name).toBe(testData.users[0].name); expect(result.data.updateUser.data.address.id).toBe(testData.addresses[0].id); expect(result.data.updateUser.data.address.city).toBe(testData.addresses[0].city); expect(result.data.updateUser.data.address.user.name).toBe(testData.users[0].name); }); test('find - make sure setting address worked', async () => { const users = gql` query users($where: JSON) { users(where: $where) { id address { id city } } } `; const result = await client.query({ query: users, variables: { where: { match: { id: testData.users[0].id } } } }); expect(result.data['users'][0].address.id).toBe(testData.addresses[0].id); expect(result.data['users'][0].address.city).toBe(testData.addresses[0].city); }); test('find - try out some fragments', async () => { const fragment = gql`fragment user on User{ name writtenSubmissions { id title } }`; const users = gql` query users($where: JSON) { users(where: $where) { id address { id city user { ...user } } } } ${fragment} `; const result = await client.query({ query: users, variables: { where: { match: { id: testData.users[0].id } } } }); expect(result.data['users'][0].address.id).toBe(testData.addresses[0].id); expect(result.data['users'][0].address.city).toBe(testData.addresses[0].city); expect(result.data['users'][0].address.user.writtenSubmissions[0].id).toBe(testData.posts[0].id); }); test('disconnect - disconnect user address', async () => { const updateAddress = gql` mutation updateAddress($input: UpdateAddressMutationInput!) { updateAddress(input: $input ) { data { id city user { id } } } } `; const result = await client.mutate({ mutation: updateAddress, variables: { input: { where: { id: testData.addresses[0].id }, data: { user: { disconnect: true } } } } }); expect(result.data.updateAddress.data.id).toBe(testData.addresses[0].id); expect(result.data.updateAddress.data.city).toBe(testData.addresses[0].city); expect(result.data.updateAddress.data.user).toBeNull(); }); test('find - make sure disconnect address worked', async () => { const users = gql` query users($where: JSON) { users(where: $where) { id address { id city } } } `; const result = await client.query({ query: users, variables: { where: { match: { id: testData.users[0].id } } } }); expect(result.data['users'][0].address).toBeNull(); }); test('create - create comment on user', async () => { const $title = 'Nice post'; const createComment = gql` mutation createComment($input: CreateCommentMutationInput!) { createComment(input: $input) { data { id title approved author { id name email } } } } `; const result = await client.mutate({ mutation: createComment, variables: { input: { data: { title: $title, author: { connect: { id: testData.users[0].id } } } } } }); testData.comments.push(result.data.createComment.data); expect(result.data.createComment.data.title).toBe($title); expect(result.data.createComment.data.approved).toBe(true); expect(result.data.createComment.data.author.id).toBe(testData.users[0].id); expect(result.data.createComment.data.author.name).toBe(testData.users[0].name); }); test('create - create another comment on user', async () => { const $title = 'Bad post'; const createComment = gql` mutation createComment($input: CreateCommentMutationInput!) { createComment(input: $input) { data { id title approved author { id name email } } } } `; const result = await client.mutate({ mutation: createComment, variables: { input: { data: { approved: false, title: $title, author: { connect: { id: testData.users[0].id } } } } } }); testData.comments.push(result.data.createComment.data); expect(result.data.createComment.data.title).toBe($title); expect(result.data.createComment.data.approved).toBe(false); expect(result.data.createComment.data.author.id).toBe(testData.users[0].id); expect(result.data.createComment.data.author.name).toBe(testData.users[0].name); }); test('find - comment is on user with default approval status', async () => { const users = gql` query users($where: JSON) { users(where: $where) { id writtenSubmissions { id title ... on Comment { approved } } } } `; const result = await client.query({ query: users, variables: { where: { match: { id: testData.users[0].id } } } }); expect(result.data['users'][0].writtenSubmissions).toHaveLength(3); expect(result.data['users'][0].writtenSubmissions[1].title).toBe(testData.comments[0].title); expect(result.data['users'][0].writtenSubmissions[1].approved).toBe(true); }); test('addTo - add comment to post and create a new one', async () => { const updatePost = gql` mutation updatePost($input: UpdatePostMutationInput!) { updatePost(input: $input ) { data { id title comments { id title approved author { name } } } } } `; const result = await client.mutate({ mutation: updatePost, variables: { input: { where: { id: testData.posts[0].id }, data: { comments: { connect: [ { id: testData.comments[0].id }, { id: testData.comments[1].id } ], create: [ { title: 'best post ever' } ] } } } } }); expect(result.data.updatePost.data.comments).toHaveLength(3); expect(result.data.updatePost.data.comments[1].id).toBe(testData.comments[0].id); expect(result.data.updatePost.data.comments[1].author.name).toBe(testData.users[0].name); expect(result.data.updatePost.data.comments[2].id).toBe(testData.comments[1].id); expect(result.data.updatePost.data.comments[0].title).toBe('best post ever'); expect(result.data.updatePost.data.comments[0].author).toBeNull(); expect(result.data.updatePost.data.comments[0].approved).toBe(true); }); test('all where - where by age', async () => { const zain = await client.mutate({ mutation: createUser, variables: { input: { data: { name: 'Zain', age: 22, birthday: '1996-01-22', email: 'zain@example.com' } } } }); const steve = await client.mutate({ mutation: createUser, variables: { input: { data: { name: 'Steve', age: 26, birthday: '1992-06-02', email: 'steve@example.com' } } } }); const pete = await client.mutate({ mutation: createUser, variables: { input: { data: { name: 'Pete', age: 30, birthday: '1988-06-02', email: 'pete@example.com' } } } }); testData.users.push(zain.data.createUser.data); testData.users.push(steve.data.createUser.data); testData.users.push(pete.data.createUser.data); const users = gql` { users(where:{ range:{ age: [23, null] } }, orderBy: { email: ASC }) { name birthday age email } } `; const result = await client.query({ query: users }); expect(result.data['users']).toHaveLength(3); expect(result.data['users'][0].email).toBe('coreyj@example.com'); expect(result.data['users'][1].email).toBe('pete@example.com'); expect(result.data['users'][2].email).toBe('steve@example.com'); }); test('all where - where by age with or', async () => { const users = gql` { users(where:{ or: [{ range:{ age: [0, 24] } }, {range:{ age: [29, null] }}] }, orderBy: { email: ASC }) { name birthday age email } } `; const result = await client.query({ query: users }); expect(result.data['users']).toHaveLength(3); expect(result.data['users'][0].email).toBe('coreyj@example.com'); expect(result.data['users'][1].email).toBe('pete@example.com'); expect(result.data['users'][2].email).toBe('zain@example.com'); }); test('all where - where by name range', async () => { const users = gql` { users(where:{ range:{ name: [ "C", "T" ] } }, orderBy: { email: ASC }) { name birthday age email } } `; const result = await client.query({ query: users }); expect(result.data['users'][0].email).toBe('coreyj@example.com'); expect(result.data['users'][1].email).toBe('pete@example.com'); expect(result.data['users'][2].email).toBe('steve@example.com'); expect(result.data['users']).toHaveLength(3); }); test('all where - where by bday range', async () => { const users = gql` { users(where:{ range:{ birthday: [ null, "1990-01-01" ] } }, orderBy: { email: ASC }) { name birthday age email } } `; const result = await client.query({ query: users }); expect(result.data['users']).toHaveLength(2); expect(result.data['users'][0].email).toBe('coreyj@example.com'); expect(result.data['users'][1].email).toBe('pete@example.com'); }); test('all where - nested match', async () => { const users = gql` { users (where: { writtenSubmissions: { match: { title: "${testData.posts[0].title}" } } }) { name email writtenSubmissions { id title } } } `; const result = await client.query({ query: users }); expect(result.data['users']).toHaveLength(1); expect(result.data['users'][0].email).toBe('coreyj@example.com'); expect(result.data['users'][0].writtenSubmissions.length).toBeGreaterThan(1); expect(result.data['users'][0].writtenSubmissions).toEqual(expect.arrayContaining([expect.objectContaining({title: testData.posts[0].title})])); }); test('all where - nested match and filter in result', async () => { const users = gql` { users (where: { writtenSubmissions: { match: { title: "${testData.posts[0].title}" } } }) { name email writtenSubmissions (where: { match: { title: "${testData.posts[0].title}" } }) { id title } } } `; const result = await client.query({ query: users }); expect(result.data['users']).toHaveLength(1); expect(result.data['users'][0].email).toBe('coreyj@example.com'); expect(result.data['users'][0].writtenSubmissions).toHaveLength(1); expect(result.data['users'][0].writtenSubmissions[0].title).toBe(testData.posts[0].title); }); test('all where - post connection', async () => { const postsConnection = gql` { postsConnection(first: 1, orderBy: {title: DESC}, after: "${testData.posts[1].id}") { edges { cursor node { id title author { name } } } pageInfo { hasNextPage hasPreviousPage startCursor endCursor } aggregate { count } } } `; const result = await client.query({ query: postsConnection }); expect(result.data['postsConnection'].edges).toHaveLength(1); expect(result.data['postsConnection'].edges[0].cursor).toBe(result.data['postsConnection'].edges[0].node.id); expect(result.data['postsConnection'].edges[0].node.id).toBe(testData.posts[0].id); expect(result.data['postsConnection'].aggregate.count).toBe(2); expect(result.data['postsConnection'].pageInfo.hasNextPage).toBe(false); expect(result.data['postsConnection'].pageInfo.hasPreviousPage).toBe(true); expect(result.data['postsConnection'].pageInfo.startCursor).toBe(testData.posts[0].id); expect(result.data['postsConnection'].pageInfo.endCursor).toBe(testData.posts[0].id); }); test('all where - post connection', async () => { const usersConnection = gql` { usersConnection(first: 2, orderBy: {name: ASC}, after: "${testData.users[0].id}") { edges { cursor node { id name email } } pageInfo { hasNextPage hasPreviousPage startCursor endCursor } aggregate { count } } } `; const result = await client.query({ query: usersConnection }); expect(result.data['usersConnection'].edges).toHaveLength(2); expect(result.data['usersConnection'].edges[0].cursor).toBe(result.data['usersConnection'].edges[0].node.id); expect(result.data['usersConnection'].aggregate.count).toBe(testData.users.length); expect(result.data['usersConnection'].pageInfo.hasNextPage).toBe(true); expect(result.data['usersConnection'].pageInfo.hasPreviousPage).toBe(true); expect(result.data['usersConnection'].pageInfo.startCursor).toBe(result.data['usersConnection'].edges[0].node.id); expect(result.data['usersConnection'].pageInfo.endCursor).toBe(result.data['usersConnection'].edges[1].node.id); }); test('find - multiple ordering', async () => { const users = gql` { users(orderBy: { name: ASC }){ name writtenSubmissions (orderBy: {title: ASC}) { title } } } `; const result = await client.query({ query: users }); const names = []; const namesSorted = []; result.data['users'].forEach(user => { names.push(user.name); namesSorted.push(user.name); if (user.writtenSubmissions) { const writtenSubmissions = []; const writtenSubmissionsSorted = []; user.writtenSubmissions.forEach(submission => { writtenSubmissions.push(submission.title); writtenSubmissionsSorted.push(submission.title); }); writtenSubmissionsSorted.sort(); expect(writtenSubmissions).toEqual(writtenSubmissionsSorted); } }); namesSorted.sort(); expect(names).toEqual(namesSorted); }); test('find - nested ordering', async () => { await client.mutate({ mutation: createPost, variables: { input: { data: { title: 'A Post', author: { connect: { id: testData.users[0].id } } } } } }); await client.mutate({ mutation: createPost, variables: { input: { data: { title: 'F Post', author: { connect: { id: testData.users[0].id } } } } } }); await client.mutate({ mutation: createPost, variables: { input: { data: { title: 'Z Post', author: { connect: { id: testData.users[0].id } } } } } }); const posts = gql` { posts(orderBy: {author: {writtenSubmissions: {title: DESC}}}){ title author { name writtenSubmissions { title } } } } `; const result = await client.query({ query: posts }); result.data['posts'].forEach(user => { if (user.author && user.author.writtenSubmissions) { const writtenSubmissions = []; const writtenSubmissionsSorted = []; user.author.writtenSubmissions.forEach(submission => { writtenSubmissions.push(submission.title); writtenSubmissionsSorted.push(submission.title); }); writtenSubmissionsSorted.sort(); writtenSubmissionsSorted.reverse(); expect(writtenSubmissions).toEqual(writtenSubmissionsSorted); } }); }); test('find - and logical operator', async () => { const users = gql` { users(where: {and: [{range: {age: [26, 30]}},{exists: {birthday: true}}]}) { name age birthday } } `; const result = await client.query({ query: users }); expect(result.data['users']).toHaveLength(3); result.data['users'].forEach(user => { expect(user.birthday).not.toBeNull(); expect(user.age).toBeLessThanOrEqual(30); expect(user.age).toBeGreaterThanOrEqual(26); }); }); test('find - or logical operator', async () => { const users = gql` { users(where: {or: [{range: {age: [26, 30]}},{exists: {birthday: true}}]}) { name age birthday } } `; const result = await client.query({ query: users }); expect.hasAssertions(); result.data['users'].forEach(user => { if (!user.birthday) { expect(user.age).toBeLessThanOrEqual(30); expect(user.age).toBeGreaterThanOrEqual(26); } else if (user.age < 26 || user.age > 30) { expect(user.birthday).not.toBeNull(); } }); }); test('find - not logical operator', async () => { const users = gql` { users(where: {not: {range: {age: [20, 26]}}}) { name age birthday } } `; const result = await client.query({ query: users }); expect.hasAssertions(); result.data['users'].forEach(user => { if (user.age) { expect(user.age).not.toBe(20); expect(user.age).not.toBe(21); expect(user.age).not.toBe(22); expect(user.age).not.toBe(23); expect(user.age).not.toBe(24); expect(user.age).not.toBe(25); expect(user.age).not.toBe(26); } }); }); test('find - node', async () => { const nodeQuery = gql` { node(id: "${testData.posts[0].id}") { id } } `; const result = await client.query({ query: nodeQuery }); expect(result.data['node']['id']).toBe(testData.posts[0].id); }); test('genie - getRawData', async () => { const nodes = await genie.getRawData(); expect(nodes).not.toBeNull(); expect(nodes.length).toBeGreaterThan(0); }); test('genie - getRawData Address only, then import', async () => { let nodes = await genie.getRawData(['Address']); expect(nodes).not.toBeNull(); expect(nodes.length).toBe(1); nodes[0].city = 'Olympus'; const result = await genie.importRawData(nodes, true); expect(result.data.length).toBeGreaterThan(0); expect(result.data[0].city).toBe('Olympus'); nodes = await genie.getRawData(['Address']); expect(nodes).not.toBeNull(); expect(nodes.length).toBe(1); expect(nodes[0].city).toBe('Olympus'); }); test('genie - importRawData with passing conditions', async () => { const nodes = await genie.getRawData(['Address']); nodes[0].city = 'Troy'; const conditions = {match: { city: 'Olympus' }}; const result = await genie.importRawData(nodes, true, '', '', [{id: nodes[0].id, conditions}]); expect(result.data.length).toBeGreaterThan(0); expect(result.data[0].city).toBe('Troy'); }); test('genie - importRawData with failing conditions', async () => { const nodes = await genie.getRawData(['Address']); const conditions = {match: { city: 'Olympus' }}; const passingConditions = {match: { city: 'Troy' }}; const result = await genie.importRawData(nodes, true, '', '', [{id: nodes[0].id, conditions}, {id: nodes[0].id, conditions: passingConditions}]); expect(result.data).toHaveLength(0); expect(result.unalteredData.length).toBeGreaterThan(0); expect(result.unalteredData[0].city).toBe('Troy'); }); test('genie - importRawData with conditions on missing data', async () => { const nodes = await genie.getRawData(['Address']); nodes[0].id = genie.getDataResolver().computeId('Address'); nodes[0].city = 'Missing'; delete nodes[0].__typename; // test getting typename from id const conditions = {match: { city: 'Troy' }}; const result = await genie.importRawData(nodes, true, '', '', [{id: nodes[0].id, conditions}]); expect(result.data).toHaveLength(0); expect(result.unalteredData).toHaveLength(0); expect(result.missingData.length).toBeGreaterThan(0); expect(result.missingData[0].city).toBe('Missing'); }); test('genie - export query', async () => { const exportData = gql` { exportData } `; const result = await client.query({ query: exportData }); expect(result.data['exportData']).not.toBeNull(); expect(result.data['exportData'].length).toBeGreaterThan(0); }); test('genie - export query and import mutation', async () => { const exportData = gql` { exportData(types: ["Address"]) } `; let result: any = await client.query({ query: exportData }); expect(result.data['exportData']).not.toBeNull(); expect(result.data['exportData'].length).toBe(1); const dataCopy = JSON.parse(JSON.stringify(result.data['exportData'])); dataCopy[0]['city'] = 'Eau Claire'; const dataString = JSON.stringify(dataCopy).replace(/\"([^(\")"]+)\":/g, '$1:'); // This will remove all the quotes around props const importData = gql` mutation { importData(data: ${dataString}, merge: true) { data unalteredData missingData } } `; result = await client.mutate({ mutation: importData }); expect(result.data['importData'].data.length).toBeGreaterThan(0); client.cache['data'].data = {}; result = await client.query({ query: exportData }); expect(result.data['exportData']).not.toBeNull(); expect(result.data['exportData'].length).toBe(1); expect(result.data['exportData'][0]['city']).toBe('Eau Claire'); }); test('genie - address query and import mutation', async () => { // set a user on an address await client.mutate({ mutation: updateUser, variables: { input: { where: { id: testData.users[0].id }, data: { address: { connect: { id: testData.addresses[0].id } } } } } }); // create a new user let hades = await client.mutate({ mutation: createUser, variables: { input: { data: { name: 'Hades', email: 'hades@example.com' } } } }); hades = hades.data.createUser.data; const addressQuery = gql` { addresses { id city user { id name } } } `; let result: any = await client.query({ query: addressQuery }); expect(result.data['addresses']).not.toBeNull(); expect(result.data['addresses'].length).toBe(1); const dataCopy = JSON.parse(JSON.stringify(result.data['addresses'])); dataCopy[0]['city'] = 'Underworld'; dataCopy[0]['user']['id'] = hades['id']; const dataString = JSON.stringify(dataCopy).replace(/\"([^(\")"]+)\":/g, '$1:'); // This will remove all the quotes around props const importData = gql` mutation { importData(data: ${dataString}, merge: true, defaultTypeName: "Address") { data unalteredData missingData } } `; result = await client.mutate({ mutation: importData }); expect(result.data['importData'].data.length).toBeGreaterThan(0); client.cache['data'].data = {}; result = await client.query({ query: addressQuery }); expect(result.data['addresses']).not.toBeNull(); expect(result.data['addresses'].length).toBe(1); expect(result.data['addresses'][0].city).toBe('Underworld'); expect(result.data['addresses'][0].user.name).toBe('Hades'); }); test('genie - export query and import mutation with date', async () => { const exportData = gql` { exportData(types: ["Comment"]) } `; let result: any = await client.query({ query: exportData }); expect(result.data['exportData']).not.toBeNull(); const dataCopy = JSON.parse(JSON.stringify(result.data['exportData'])); const date = new Date(); dataCopy[0]['text'] = 'Import Data'; dataCopy[0]['updated'] = date; const dataString = JSON.stringify(dataCopy).replace(/\"([^(\")"]+)\":/g, '$1:'); // This will remove all the quotes around props const importData = gql` mutation { importData(data: ${dataString}, merge: true) { data unalteredData missingData } } `; result = await client.mutate({ mutation: importData }); expect(result.data['importData'].data.length).toBeGreaterThan(0); client.cache['data'].data = {}; result = await client.query({ query: exportData }); expect(result.data['exportData']).not.toBeNull(); expect(result.data['exportData'][0]['text']).toBe('Import Data'); const dateScalar = genie.getSchema().getType('DateTime'); expect(result.data['exportData'][0]['updated']).toEqual(dateScalar.serialize(date)); }); test('genie - disconnect', async () => { const disconReturn = await genie.disconnect(); expect(disconReturn).toBeTruthy(); }); test('genie - connect', async () => { const conReturn = await genie.connect(); expect(conReturn).toBeTruthy(); }); test('genie - relation test', async () => { const typeDefs = gql` type Comment { id: ID! @unique createdAt: DateTime @createdTimestamp updatedAt: DateTime @updatedTimestamp author: User @relation(name: "commentsByUser") body: String post: Post @relation(name: "commentsOnPost") } enum postType { TEXT LINK } type Post { id: ID! @unique createdAt: DateTime @createdTimestamp updatedAt: DateTime @updatedTimestamp author: User @relation(name: "postsByUser") type: postType comments: [Comment!] @relation(name: "commentsOnPost") } type User { id: ID! @unique createdAt: DateTime @createdTimestamp updatedAt: DateTime @updatedTimestamp userName: String! @unique posts: [Post!] @relation(name: "postsByUser") comments: [Comment!] @relation(name: "commentsByUser") } `; const fortuneOptions = { settings: { enforceLinks: true } }; const genie = new GraphQLGenie({ typeDefs, fortuneOptions, generatorOptions: { generateGetAll: true, generateCreate: true, generateUpdate: true, generateDelete: true, generateUpsert: true, }, }); const client = getClient(genie); const result: any = await client.query({ query: gql`{ users { id } }` }); expect(result).toBeDefined(); }); test('genie - another relation test', async () => { const typeDefs = gql` type Person { id: ID! @unique name: String! devices: [Device!] bugReports: [BugReport!] } type Device { id: ID! @unique hostname: String! person: Person } type BugReport { id: ID! @unique summary: String! person: Person } `; const fortuneOptions = { settings: { enforceLinks: true } }; const genie = new GraphQLGenie({ typeDefs, fortuneOptions }); const client = getClient(genie); const result: any = await client.query({ query: gql`{ devices { id } }` }); expect(result).toBeDefined(); }); });