import { ApolloClient } from 'apollo-client'; import gql from 'graphql-tag'; import { getClient } from '../setupTests'; let client: ApolloClient; beforeAll(() => { 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 } } `; describe('mutationTests', () => { test('create - user with posts', async () => { const user = await client.mutate({ mutation: gql` mutation { createUser( input: { data: { age: 42 email: "zeus@example.com" name: "Zeus" writtenSubmissions: { posts: { create: [{ title: "Hello World" text: "This is my first blog post ever!" }, { title: "My Second Post" text: "My first post was good, but this one is better!" }, { title: "Solving World Hunger" text: "This is a draft..." }] } } } clientMutationId: "Test" } ) { data { id age name email writtenSubmissions { id title } } clientMutationId } } ` }); testData.users.push(user.data.createUser.data); testData.posts = testData.posts.concat(user.data.createUser.data.writtenSubmissions); expect(user.data.createUser.clientMutationId).toBe('Test'); expect(user.data.createUser.data.name).toBe('Zeus'); expect(user.data.createUser.data.age).toBe(42); expect(user.data.createUser.data.email).toBe('zeus@example.com'); expect(user.data.createUser.data.writtenSubmissions).toHaveLength(3); expect(user.data.createUser.data.writtenSubmissions[0].title).toBe('Hello World'); expect(user.data.createUser.data.writtenSubmissions[1].title).toBe('My Second Post'); expect(user.data.createUser.data.writtenSubmissions[2].title).toBe('Solving World Hunger'); }); test('create - create post connect author', async () => { const date = new Date(1988, 2, 23); const post = await client.mutate({ mutation: gql`mutation { createPost( input: { data: { title: "Genie is great" text: "Look how fast I can create an executable schema" tags: ["genie", "graphql", "database"] author: { connect:{ email: "zeus@example.com" } } created: "${date.toISOString()}" createdManual: "${date.toISOString()}" } } ) { data { id title text tags author { email } created createdManual } } } ` }); testData.posts.push(post.data.createPost.data); expect(post.data.createPost.data.title).toBe('Genie is great'); expect(post.data.createPost.data.text).toBe('Look how fast I can create an executable schema'); expect(post.data.createPost.data.tags).toEqual(['genie', 'graphql', 'database']); expect(post.data.createPost.data.author.email).toBe('zeus@example.com'); const created = new Date(post.data.createPost.data.created); expect(created > date).toBe(true); const createdManual = new Date(post.data.createPost.data.createdManual); expect(createdManual.getTime()).toBe(date.getTime()); }); test('update - push onto tags', async () => { const post = await client.mutate({ mutation: gql`mutation { updatePost( input: { data: { tags: { push: ["fortune"] } } where: { id: "${testData.posts[3].id}" } } ) { data { id tags } } } ` }); expect(post.data.updatePost.data.tags).toEqual(['genie', 'graphql', 'database', 'fortune']); }); test('update - push duplicate onto tags', async () => { const post = await client.mutate({ mutation: gql`mutation { updatePost( input: { data: { tags: { push: ["fortune"] } } where: { id: "${testData.posts[3].id}" } } ) { data { id tags created updated } } } ` }); expect(post.data.updatePost.data.created).not.toBeFalsy(); expect(post.data.updatePost.data.updated).not.toBeFalsy(); testData.posts[3].updated = new Date(post.data.updatePost.data.updated); expect(post.data.updatePost.data.tags).toEqual(['genie', 'graphql', 'database', 'fortune', 'fortune']); }); test('update - push test conditions passing', async () => { const post = await client.mutate({ mutation: gql`mutation { updatePost( input: { data: { tags: { push: ["apollo"] } } where: { id: "${testData.posts[3].id}" }, conditions: { range: {created: ["2018-01-01T01:00:00.000Z", null]} } } ) { data { id tags created updated } } } ` }); expect(post.data.updatePost.data.created).not.toBeFalsy(); const updated = new Date(post.data.updatePost.data.updated); expect(updated > testData.posts[3].updated).toBe(true); testData.posts[3].updated = updated; expect(post.data.updatePost.data.tags).toEqual(['genie', 'graphql', 'database', 'fortune', 'fortune', 'apollo']); }); test('update - push test conditions not passing', async () => { const post = await client.mutate({ mutation: gql`mutation { updatePost( input: { data: { tags: { push: ["old"] } } where: { id: "${testData.posts[3].id}" }, conditions: { range: {created: [null, "2018-01-01T01:00:00.000Z"]} } } ) { data { id tags created updated } unalteredData { id tags created updated } } } ` }); expect(post.data.updatePost.data).toBe(null); expect(testData.posts[3].updated).toEqual(new Date(post.data.updatePost.unalteredData.updated)); expect(post.data.updatePost.unalteredData.tags).not.toContain('old'); expect(post.data.updatePost.unalteredData.tags).toEqual(['genie', 'graphql', 'database', 'fortune', 'fortune', 'apollo']); }); test('update - updated set to passed in value', async () => { const date = new Date(1988, 2, 23); const post = await client.mutate({ mutation: gql`mutation { updatePost( input: { data: { updated: "${date.toISOString()}" updatedManual: "${date.toISOString()}" } where: { id: "${testData.posts[0].id}" } } ) { data { id updated updatedManual } } } ` }); const updated = new Date(post.data.updatePost.data.updated); expect(updated > date).toBe(true); const updatedManual = new Date(post.data.updatePost.data.updatedManual); expect(updatedManual.getTime()).toBe(date.getTime()); }); test('update - pull from tags', async () => { const post = await client.mutate({ mutation: gql`mutation { updatePost( input: { data: { tags: { pull: ["fortune"] } } where: { id: "${testData.posts[3].id}" } } ) { data { id tags updated } } } ` }); expect(post.data.updatePost.data.tags).toEqual(['genie', 'graphql', 'database', 'apollo']); const updated = new Date(post.data.updatePost.data.updated); expect(updated > testData.posts[3].updated).toBe(true); testData.posts[3].updated = updated; }); test('update - set tags', async () => { const post = await client.mutate({ mutation: gql`mutation { updatePost( input: { data: { tags: { set: ["fortune"] } } where: { id: "${testData.posts[3].id}" } } ) { data { id tags } } } ` }); expect(post.data.updatePost.data.tags).toEqual(['fortune']); }); test('update - create address on user and update age', async () => { const user = await client.mutate({ mutation: gql`mutation { updateUser( input: { data: { age: 5000 address: { create: { city: "Olympus" } } } where: { email: "zeus@example.com" } } ) { data { id name email age address { city user { name } } } } } ` }); expect(user.data.updateUser.data.name).toBe('Zeus'); expect(user.data.updateUser.data.age).toBe(5000); expect(user.data.updateUser.data.email).toBe('zeus@example.com'); expect(user.data.updateUser.data.address.city).toBe('Olympus'); expect(user.data.updateUser.data.address.user.name).toBe('Zeus'); }); test('update - disconnect address on user', async () => { const user = await client.mutate({ mutation: gql`mutation { updateUser( input: { data: { address: { disconnect: true } } where: { email: "zeus@example.com" } } ) { data { id name email age address { city } } } } ` }); expect(user.data.updateUser.data.name).toBe('Zeus'); expect(user.data.updateUser.data.age).toBe(5000); expect(user.data.updateUser.data.email).toBe('zeus@example.com'); expect(user.data.updateUser.data.address).toBeNull(); }); test('update - update posts on user with age', async () => { const secondPostId = testData.posts[1].id; const user = await client.mutate({ mutation: gql`mutation { updateUser( input: { data: { age: 5001 writtenSubmissions: { posts: { update: [ { data: { title: "My Updated Post" tags: { set: ["updated"] } } where: { id: "${secondPostId}" } } ] } } } where: { email: "zeus@example.com" } } ) { data { id name email age writtenSubmissions { title tags } } } } ` }); expect(user.data.updateUser.data.name).toBe('Zeus'); expect(user.data.updateUser.data.age).toBe(5001); expect(user.data.updateUser.data.email).toBe('zeus@example.com'); expect(user.data.updateUser.data.writtenSubmissions[1].title).toBe('My Updated Post'); expect(user.data.updateUser.data.writtenSubmissions[1].tags).toEqual(['updated']); }); test('upsert - create new user', async () => { const user = await client.mutate({ mutation: gql`mutation { upsertUser( input: { create: { name: "Corey" email: "corey@example.com" } update: { age: 30 } where: { email: "corey@example.com" } } ) { data { id name email age } } } ` }); testData.users.push(user.data.upsertUser.data); expect(user.data.upsertUser.data.name).toBe('Corey'); expect(user.data.upsertUser.data.age).toBeNull(); expect(user.data.upsertUser.data.email).toBe('corey@example.com'); }); test('upsert - update upserted user', async () => { const user = await client.mutate({ mutation: gql`mutation { upsertUser( input: { create: { name: "Corey" email: "corey@example.com" } update: { age: 30 } where: { email: "corey@example.com" } } ) { data { id name email age } } } ` }); expect(user.data.upsertUser.data.name).toBe('Corey'); expect(user.data.upsertUser.data.age).toBe(30); expect(user.data.upsertUser.data.email).toBe('corey@example.com'); }); test('upsert - nested upsert create family member on user', async () => { const user = await client.mutate({ mutation: gql`mutation { updateUser( input: { data: { family: { upsert: [ { update: { age: 4950 } create: { name: "Loki" email: "loki@example.com" } where:{ email: "loki@example.com" } } ] } } where: { email: "zeus@example.com" } } ) { data { id name email age family { name email age } } } } ` }); expect(user.data.updateUser.data.email).toBe('zeus@example.com'); expect(user.data.updateUser.data.family[0].name).toBe('Loki'); expect(user.data.updateUser.data.family[0].email).toBe('loki@example.com'); expect(user.data.updateUser.data.family[0].age).toBeNull(); }); test('upsert - nested upsert update family member on user', async () => { const user = await client.mutate({ mutation: gql`mutation { updateUser( input: { data: { family: { upsert: [ { update: { age: 4950 } create: { name: "Loki" email: "loki@example.com" } where:{ email: "loki@example.com" } } ] } } where: { email: "zeus@example.com" } } ) { data { id name email age family { name email age } } } } ` }); expect(user.data.updateUser.data.email).toBe('zeus@example.com'); expect(user.data.updateUser.data.family[0].name).toBe('Loki'); expect(user.data.updateUser.data.family[0].email).toBe('loki@example.com'); expect(user.data.updateUser.data.family[0].age).toBe(4950); }); test('upsert - nested upsert create address member on user', async () => { const user = await client.mutate({ mutation: gql`mutation { updateUser( input: { data: { address: { upsert: { create: { city: "New York" } update: { city: "Olympus" } } } } where: { email: "zeus@example.com" } } ) { data { id name email age address { id city } } } } ` }); testData.addresses.push(user.data.updateUser.data.address); expect(user.data.updateUser.data.email).toBe('zeus@example.com'); expect(user.data.updateUser.data.address.city).toBe('New York'); }); test('upsert - nested upsert update address member on user', async () => { const user = await client.mutate({ mutation: gql`mutation { updateUser( input: { data: { address: { upsert: { create: { city: "New York" } update: { city: "Olympus" } } } } where: { email: "zeus@example.com" } } ) { data { id name email age address { id city } } } } ` }); expect(user.data.updateUser.data.email).toBe('zeus@example.com'); expect(user.data.updateUser.data.address.city).toBe('Olympus'); }); test('update - nested update update address member on user', async () => { const user = await client.mutate({ mutation: gql`mutation { updateUser( input: { data: { address: { update: { city: "Eau Claire" } } } where: { email: "zeus@example.com" } } ) { data { id name email age address { id city } } } } ` }); expect(user.data.updateUser.data.email).toBe('zeus@example.com'); expect(user.data.updateUser.data.address.city).toBe('Eau Claire'); }); test('delete - delete user', async () => { const user = await client.mutate({ mutation: gql`mutation { deleteUser(input: { where: { email: "corey@example.com" } }) { data { id name email } } } ` }); expect(user.data.deleteUser.data.email).toBe('corey@example.com'); }); test('update - delete address from user', async () => { const user = await client.mutate({ mutation: gql`mutation { updateUser( input: { data: { address: { delete: true } } where: { email: "zeus@example.com" } } ) { data { id name age address { id city } } } } ` }); expect(user.data.updateUser.data.address).toBeNull(); }); test('find - make sure address is deleted', async () => { const addresses = gql` query addresses($where: JSON) { addresses(where: $where) { id } } `; const result = await client.query({ query: addresses, variables: { where: { match: { id: testData.addresses[0].id } } } }); expect(result.data['addresses']).toHaveLength(0); }); test('update - delete post on user', async () => { const secondPostId = testData.posts[1].id; const user = await client.mutate({ mutation: gql`mutation { updateUser( input: { data: { writtenSubmissions: { posts: { delete: [{ id: "${secondPostId}"}] } } } where: { email: "zeus@example.com" } } ) { data { id name email age writtenSubmissions { title } } } } ` }); expect(user.data.updateUser.data.email).toBe('zeus@example.com'); expect(user.data.updateUser.data.writtenSubmissions).toHaveLength(3); }); test('find - make sure post is deleted', async () => { const posts = gql` query posts($where: JSON) { posts(where: $where) { id } } `; const result = await client.query({ query: posts, variables: { where: { match: { id: testData.posts[1].id } } } }); expect(result.data['posts']).toHaveLength(0); }); test('update - update many users', async () => { const zain = await client.mutate({ mutation: createUser, variables: { input: { data: { name: 'Zain', birthday: '1996-01-22', email: 'zain@example.com' } } } }); const steve = await client.mutate({ mutation: createUser, variables: { input: { data: { name: 'Steve', birthday: '1992-06-02', email: 'steve@example.com' } } } }); const pete = await client.mutate({ mutation: createUser, variables: { input: { data: { name: 'Pete', 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 updateManyUsers = gql` mutation { updateManyUsers(input: { where: { exists: { age: false } } data: { age: 12 } }) { count } } `; const result = await client.mutate({ mutation: updateManyUsers }); const findPete = gql` { users(email: "pete@example.com") { age } } `; const peteResult = await client.query({ query: findPete }); expect(result.data['updateManyUsers'].count).toBe(3); expect(peteResult.data['users']).toHaveLength(1); expect(peteResult.data['users'][0].age).toBe(12); }); test('update - update many users, try to set unique field', async () => { const updateManyUsers = gql` mutation { updateManyUsers(input: { where: { exists: { age: true } } data: { email: "this update should fail" } }) { count } } `; expect.assertions(2); try { await client.mutate({ mutation: updateManyUsers }); } catch (e) { expect(e).not.toBeNull(); expect(e['message']).toContain('multiple'); } }); test('create - unique field check', async () => { const createPost = gql` mutation { createPost( input: { data: { title: "should not create" author: { create: { name: "zeus" email: "zeus@example.com" } } } clientMutationId: "Test" } ) { data { id title } clientMutationId } } `; expect.assertions(2); try { await client.mutate({ mutation: createPost }); } catch (e) { expect(e).not.toBeNull(); expect(e['message']).toContain('duplicate'); } }); test('deleteMany - users age 12', async () => { const deleteManyUsers = gql` mutation { deleteManyUsers(input: { where: { match: { age: 12 } } }) { count } } `; const result = await client.mutate({ mutation: deleteManyUsers }); const findPete = gql` { users(email: "pete@example.com") { age } } `; const peteResult = await client.query({ query: findPete }); expect(result.data['deleteManyUsers'].count).toBe(3); expect(peteResult.data['users'][0]).toBeNull(); }); test('createUser - with creating union types', async () => { const createUser = gql` mutation { createUser(input: {data: {name: "joe", email: "joe@example.com", starred: { users: { create: { name: "jim", email: "jim@example.com" } } comments: { create: { title: "bam" } } } }}) { data { name starred { ...on User { name email } ...on Submission { title } } } } } `; const result = await client.mutate({ mutation: createUser }); expect(result.data['createUser'].data.name).toBe('joe'); expect(result.data['createUser'].data.starred[0].name).toBe('jim'); expect(result.data['createUser'].data.starred[1].title).toBe('bam'); }); });