Skip to content

[WIP]1706 refactor shout spec#1712

Closed
Tirokk wants to merge 4 commits intopr1712basefrom
pr1712head
Closed

[WIP]1706 refactor shout spec#1712
Tirokk wants to merge 4 commits intopr1712basefrom
pr1712head

Conversation

@Tirokk
Copy link
Member

@Tirokk Tirokk commented Oct 5, 2020

aonomike Authored by aonomike
Sep 25, 2019
Merged Sep 29, 2019


🍰 Pullrequest

Refactor shout spec to use apollo-server-testing

Issues

  • None

Todo

  • Implement the unshout path

shoutedByCurrentUser: false,
}
expect(Post[0]).toMatchObject(expected2)
it('my own post', async () => {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

roschaefer Authored by roschaefer
Sep 28, 2019


Outdated (history rewrite) - original diff


@@ -19,141 +19,148 @@ const mutationUnshoutPost = gql`
     unshout(id: $id, type: Post)
   }
 `
-const createPostMutation = gql`
-  mutation($id: ID, $title: String!, $content: String!, $categoryIds: [ID]!) {
-    CreatePost(id: $id, title: $title, content: $content, categoryIds: $categoryIds) {
+const queryPost = gql`
+  query($id: ID!) {
+    Post(id: $id) {
       id
-      title
-      content
+      shoutedBy {
+        id
+      }
     }
   }
 `
-const createPostVariables = {
-  id: 'p1234',
-  title: 'Post Title 1234',
-  content: 'Some Post Content 1234',
-  categoryIds,
-}
-beforeEach(async () => {
-  await factory.create('User', {
-    id: 'u1',
-    email: 'test@example.org',
-    password: '1234',
-  })
-  await factory.create('User', {
-    id: 'u2',
-    email: 'test2@example.org',
-    password: '1234',
-  })
-  await instance.create('Category', {
-    id: 'cat9',
-    name: 'Democracy & Politics',
-    icon: 'university',
-  })
-  headersUser1 = await login({ email: 'test@example.org', password: '1234' })
-  headersUser2 = await login({ email: 'test2@example.org', password: '1234' })
-  clientUser1 = new GraphQLClient(host, { headers: headersUser1 })
-  clientUser2 = new GraphQLClient(host, { headers: headersUser2 })
 
-  await clientUser1.request(createPostMutation, createPostVariables)
-  await clientUser2.request(createPostMutation, {
-    id: 'p12345',
-    title: 'Post Title 12345',
-    content: 'Some Post Content 12345',
-    categoryIds,
+describe('shout and unshout posts', () => {
+  let currentUser, postAuthor
+  beforeAll(() => {
+    authenticatedUser = undefined
+    const { server } = createServer({
+      context: () => {
+        return {
+          driver,
+          neode: instance,
+          user: authenticatedUser,
+        }
+      },
+    })
+    mutate = createTestClient(server).mutate
+    query = createTestClient(server).query
+  })
+  afterEach(() => {
+    factory.cleanDatabase()
   })
-})
-
-afterEach(async () => {
-  await factory.cleanDatabase()
-})
 
-describe('shout', () => {
-  describe('shout foreign post', () => {
-    describe('unauthenticated shout', () => {
+  describe('shout', () => {
+    describe('unauthenticated', () => {
       it('throws authorization error', async () => {
-        const client = new GraphQLClient(host)
-        await expect(client.request(mutationShoutPost, { id: 'p1234' })).rejects.toThrow(
-          'Not Authorised',
-        )
+        variables = { id: 'post-to-shout-id' }
+        authenticatedUser = undefined
+        await expect(mutate({ mutation: mutationShoutPost, variables })).resolves.toMatchObject({
+          errors: [{ message: 'Not Authorised!' }],
+        })
       })
     })
+    describe('authenticated', () => {
+      beforeEach(async () => {
+        currentUser = await factory.create('User', {
+          id: 'current-user-id',
+          name: 'Current User',
+          email: 'current.user@example.org',
+          password: '1234',
+        })
 
-    it('I shout a post of another user', async () => {
-      const res = await clientUser1.request(mutationShoutPost, { id: 'p12345' })
-      const expected = {
-        shout: true,
-      }
-      expect(res).toMatchObject(expected)
-
-      const { Post } = await clientUser1.request(gql`
-        query {
-          Post(id: "p12345") {
-            shoutedByCurrentUser
-          }
-        }
-      `)
-      const expected2 = {
-        shoutedByCurrentUser: true,
-      }
-      expect(Post[0]).toMatchObject(expected2)
-    })
+        postAuthor = await factory.create('User', {
+          id: 'post-author-id',
+          name: 'Post Author',
+          email: 'post.author@example.org',
+          password: '1234',
+        })
+        authenticatedUser = await currentUser.toJson()
+        await factory.create('Post', {
+          name: 'Other user post',
+          id: 'another-user-post-id',
+          author: postAuthor,
+        })
+        await factory.create('Post', {
+          name: 'current user post',
+          id: 'current-user-post-id',
+          author: currentUser,
+        })
+        variables = {}
+      })
 
-    it('I can`t shout my own post', async () => {
-      const res = await clientUser1.request(mutationShoutPost, { id: 'p1234' })
-      const expected = {
-        shout: false,
-      }
-      expect(res).toMatchObject(expected)
+      it("another user's post", async () => {
+        variables = { id: 'another-user-post-id' }
+        await expect(mutate({ mutation: mutationShoutPost, variables })).resolves.toMatchObject({
+          data: { shout: true },
+        })
+        await expect(query({ query: queryPost, variables })).resolves.toMatchObject({
+          data: { Post: [{ id: 'another-user-post-id', shoutedBy: [{ id: 'current-user-id' }] }] },
+          errors: undefined,
+        })
+      })
 
-      const { Post } = await clientUser1.request(gql`
-        query {
-          Post(id: "p1234") {
-            shoutedByCurrentUser
-          }
-        }
-      `)
-      const expected2 = {
-        shoutedByCurrentUser: false,
-      }
-      expect(Post[0]).toMatchObject(expected2)
+      it('my own post', async () => {

As an improvement, you can think of the it as a beginning of the sentence. E.g.:

it ... does something

So here it would be better to write "it is allowed to shout your own post" than "it my own post" which is no proper English.

await expect(mutate({ mutation: mutationUnshoutPost, variables })).resolves.toMatchObject({
data: { unshout: true },
})
await expect(query({ query: queryPost, variables })).resolves.toMatchObject({
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

roschaefer Authored by roschaefer
Sep 29, 2019


Outdated (history rewrite) - original diff


@@ -19,141 +19,148 @@ const mutationUnshoutPost = gql`
     unshout(id: $id, type: Post)
   }
 `
-const createPostMutation = gql`
-  mutation($id: ID, $title: String!, $content: String!, $categoryIds: [ID]!) {
-    CreatePost(id: $id, title: $title, content: $content, categoryIds: $categoryIds) {
+const queryPost = gql`
+  query($id: ID!) {
+    Post(id: $id) {
       id
-      title
-      content
+      shoutedBy {
+        id
+      }
     }
   }
 `
-const createPostVariables = {
-  id: 'p1234',
-  title: 'Post Title 1234',
-  content: 'Some Post Content 1234',
-  categoryIds,
-}
-beforeEach(async () => {
-  await factory.create('User', {
-    id: 'u1',
-    email: 'test@example.org',
-    password: '1234',
-  })
-  await factory.create('User', {
-    id: 'u2',
-    email: 'test2@example.org',
-    password: '1234',
-  })
-  await instance.create('Category', {
-    id: 'cat9',
-    name: 'Democracy & Politics',
-    icon: 'university',
-  })
-  headersUser1 = await login({ email: 'test@example.org', password: '1234' })
-  headersUser2 = await login({ email: 'test2@example.org', password: '1234' })
-  clientUser1 = new GraphQLClient(host, { headers: headersUser1 })
-  clientUser2 = new GraphQLClient(host, { headers: headersUser2 })
 
-  await clientUser1.request(createPostMutation, createPostVariables)
-  await clientUser2.request(createPostMutation, {
-    id: 'p12345',
-    title: 'Post Title 12345',
-    content: 'Some Post Content 12345',
-    categoryIds,
+describe('shout and unshout posts', () => {
+  let currentUser, postAuthor
+  beforeAll(() => {
+    authenticatedUser = undefined
+    const { server } = createServer({
+      context: () => {
+        return {
+          driver,
+          neode: instance,
+          user: authenticatedUser,
+        }
+      },
+    })
+    mutate = createTestClient(server).mutate
+    query = createTestClient(server).query
+  })
+  afterEach(() => {
+    factory.cleanDatabase()
   })
-})
-
-afterEach(async () => {
-  await factory.cleanDatabase()
-})
 
-describe('shout', () => {
-  describe('shout foreign post', () => {
-    describe('unauthenticated shout', () => {
+  describe('shout', () => {
+    describe('unauthenticated', () => {
       it('throws authorization error', async () => {
-        const client = new GraphQLClient(host)
-        await expect(client.request(mutationShoutPost, { id: 'p1234' })).rejects.toThrow(
-          'Not Authorised',
-        )
+        variables = { id: 'post-to-shout-id' }
+        authenticatedUser = undefined
+        await expect(mutate({ mutation: mutationShoutPost, variables })).resolves.toMatchObject({
+          errors: [{ message: 'Not Authorised!' }],
+        })
       })
     })
+    describe('authenticated', () => {
+      beforeEach(async () => {
+        currentUser = await factory.create('User', {
+          id: 'current-user-id',
+          name: 'Current User',
+          email: 'current.user@example.org',
+          password: '1234',
+        })
 
-    it('I shout a post of another user', async () => {
-      const res = await clientUser1.request(mutationShoutPost, { id: 'p12345' })
-      const expected = {
-        shout: true,
-      }
-      expect(res).toMatchObject(expected)
-
-      const { Post } = await clientUser1.request(gql`
-        query {
-          Post(id: "p12345") {
-            shoutedByCurrentUser
-          }
-        }
-      `)
-      const expected2 = {
-        shoutedByCurrentUser: true,
-      }
-      expect(Post[0]).toMatchObject(expected2)
-    })
+        postAuthor = await factory.create('User', {
+          id: 'post-author-id',
+          name: 'Post Author',
+          email: 'post.author@example.org',
+          password: '1234',
+        })
+        authenticatedUser = await currentUser.toJson()
+        await factory.create('Post', {
+          name: 'Other user post',
+          id: 'another-user-post-id',
+          author: postAuthor,
+        })
+        await factory.create('Post', {
+          name: 'current user post',
+          id: 'current-user-post-id',
+          author: currentUser,
+        })
+        variables = {}
+      })
 
-    it('I can`t shout my own post', async () => {
-      const res = await clientUser1.request(mutationShoutPost, { id: 'p1234' })
-      const expected = {
-        shout: false,
-      }
-      expect(res).toMatchObject(expected)
+      it("another user's post", async () => {
+        variables = { id: 'another-user-post-id' }
+        await expect(mutate({ mutation: mutationShoutPost, variables })).resolves.toMatchObject({
+          data: { shout: true },
+        })
+        await expect(query({ query: queryPost, variables })).resolves.toMatchObject({
+          data: { Post: [{ id: 'another-user-post-id', shoutedBy: [{ id: 'current-user-id' }] }] },
+          errors: undefined,
+        })
+      })
 
-      const { Post } = await clientUser1.request(gql`
-        query {
-          Post(id: "p1234") {
-            shoutedByCurrentUser
-          }
-        }
-      `)
-      const expected2 = {
-        shoutedByCurrentUser: false,
-      }
-      expect(Post[0]).toMatchObject(expected2)
+      it('my own post', async () => {
+        variables = { id: 'current-user-post-id' }
+        await expect(mutate({ mutation: mutationShoutPost, variables })).resolves.toMatchObject({
+          data: { shout: false },
+        })
+        await expect(query({ query: queryPost, variables })).resolves.toMatchObject({
+          data: { Post: [{ id: 'current-user-post-id', shoutedBy: [] }] },
+          errors: undefined,
+        })
+      })
     })
   })
-
-  describe('unshout foreign post', () => {
-    describe('unauthenticated shout', () => {
+  describe('unshout', () => {
+    describe('unauthenticated', () => {
       it('throws authorization error', async () => {
-        // shout
-        await clientUser1.request(mutationShoutPost, { id: 'p12345' })
-        // unshout
-        const client = new GraphQLClient(host)
-        await expect(client.request(mutationUnshoutPost, { id: 'p12345' })).rejects.toThrow(
-          'Not Authorised',
-        )
+        authenticatedUser = undefined
+        variables = { id: 'post-to-shout-id' }
+        await expect(mutate({ mutation: mutationUnshoutPost, variables })).resolves.toMatchObject({
+          errors: [{ message: 'Not Authorised!' }],
+        })
       })
     })
 
-    it('I unshout a post of another user', async () => {
-      // shout
-      await clientUser1.request(mutationShoutPost, { id: 'p12345' })
-      const expected = {
-        unshout: true,
-      }
-      // unshout
-      const res = await clientUser1.request(mutationUnshoutPost, { id: 'p12345' })
-      expect(res).toMatchObject(expected)
+    describe('authenticated', () => {
+      beforeEach(async () => {
+        currentUser = await factory.create('User', {
+          id: 'current-user-id',
+          name: 'Current User',
+          email: 'current.user@example.org',
+          password: '1234',
+        })
 
-      const { Post } = await clientUser1.request(gql`
-        query {
-          Post(id: "p12345") {
-            shoutedByCurrentUser
-          }
-        }
-      `)
-      const expected2 = {
-        shoutedByCurrentUser: false,
-      }
-      expect(Post[0]).toMatchObject(expected2)
+        postAuthor = await factory.create('User', {
+          id: 'id-of-another-user',
+          name: 'Another User',
+          email: 'another.user@example.org',
+          password: '1234',
+        })
+        authenticatedUser = await currentUser.toJson()
+        await factory.create('Post', {
+          name: 'Posted By Another User',
+          id: 'posted-by-another-user',
+          author: postAuthor,
+        })
+        await mutate({
+          mutation: mutationShoutPost,
+          variables: { id: 'posted-by-another-user' },
+        })
+        variables = {}
+      })
+
+      it("another user's post", async () => {
+        variables = { id: 'posted-by-another-user' }
+        await expect(mutate({ mutation: mutationUnshoutPost, variables })).resolves.toMatchObject({
+          data: { unshout: true },
+        })
+        await expect(query({ query: queryPost, variables })).resolves.toMatchObject({

You can avoid false negatives by repeating the assertion before and after you do the action. Consider that it might be shoutedBy: [] already before you called the mutation.

In ruby land we would have the expect{ ... }.to change{ ... } matcher. In JavaScript, I'm afraid, you have to repeat a method before and after you do sth.

@Tirokk
Copy link
Member Author

Tirokk commented Oct 6, 2020

roschaefer Authored by roschaefer
Sep 29, 2019


Only three backend tests left that use GraphQLClient:

$ git grep 'GraphQLClient'
src/middleware/permissionsMiddleware.spec.js:import { GraphQLClient } from 'graphql-request'
src/middleware/permissionsMiddleware.spec.js:        const graphQLClient = new GraphQLClient(host, { headers })
src/schema/resolvers/reports.spec.js:import { GraphQLClient } from 'graphql-request'
src/schema/resolvers/reports.spec.js:    client = new GraphQLClient(host, {
src/schema/resolvers/rewards.spec.js:import { GraphQLClient } from 'graphql-request'
src/schema/resolvers/rewards.spec.js:        client = new GraphQLClient(host)
src/schema/resolvers/rewards.spec.js:        client = new GraphQLClient(host, { headers })
src/schema/resolvers/rewards.spec.js:        client = new GraphQLClient(host, { headers })
src/schema/resolvers/rewards.spec.js:        const client = new GraphQLClient(host)
src/schema/resolvers/rewards.spec.js:        client = new GraphQLClient(host)
src/schema/resolvers/rewards.spec.js:        client = new GraphQLClient(host, { headers })
src/schema/resolvers/rewards.spec.js:        client = new GraphQLClient(host, { headers })
src/seed/factories/index.js:import { GraphQLClient, request } from 'graphql-request'
src/seed/factories/index.js:  const graphQLClient = new GraphQLClient(seedServerHost)
src/seed/factories/index.js:      this.graphQLClient = new GraphQLClient(seedServerHost, {
test/features/support/steps.js:import { GraphQLClient } from 'graphql-request'
test/features/support/steps.js:const client = new GraphQLClient(host)

Copy link
Contributor

@Mogge Mogge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is amazing @aonomike! I have a couple of suggestions which you can adopt in the future - but I give this PR a 👍

amazing

@Mogge Mogge closed this Oct 8, 2020
@ulfgebhardt ulfgebhardt deleted the pr1712head branch January 7, 2021 07:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants