[ PART 5 ] Creating a Twitter clone with GraphQL, Typescript, and React ( Adding tests for authorization )
Tags: showdev, career, javascript, node
Published: 2021-01-08 14:36:28

Hi everyone ;).

[Github Repository](https://github.com/ips-coding-challenge/challenge_twitter)

In the last article we didn't write any tests to verify that our **authChecker** was doing its job. And this is the first "problem" I've encountered since I started this project. The test client provided by the **apollo-server-testing** library does not, from what I have seen, propose to directly add headers to our request. After a little research, I found a solution not very complicated in itself but I don't know if it could be better ;). I propose you my solution but don't hesitate to propose others. I may even have missed something in the documentation ;).

*src/server.ts*

```typescript
export const defaultContext = ({ req, res }: any) => {
  return {
    req,
    res,
    db,
  }
}

export const schema = async () => {
  return await buildSchema({
    resolvers: [AuthResolver],
    authChecker: authChecker,
  })
}

const createServer = async () => {
  return new ApolloServer({
    schema: await schema(),
    context: defaultContext,
  })
}

export default createServer
```

I've separated things a bit in my **createServer()** method to be able to create the Test Server more easily.

*src/tests/setup.ts*

```typescript
import { ApolloServer } from 'apollo-server'
import { createTestClient } from 'apollo-server-testing'
import { defaultContext, schema } from '../server'

export const testClient = async (ctxArg: any = { req: { headers: {} } }) => {
  return createTestClient(
    new ApolloServer({
      schema: await schema(),
      context: () => defaultContext(ctxArg),
    })
  )
}

```

By default, it would seem that the TestClient does not pass headers when making queries. Since our middleware verifies that we have a header authorization, we'll just have to pass our token when we want to test the authorizations with our JWT token.

In application, it gives this:

*src/tests/auth.test.ts*

```typescript
test('it should fetch the currentUser', async () => {
  const user = await createUser()

  const { query } = await testClient({
    req: { headers: { authorization: 'Bearer ' + generateToken(user) } },
  })

  const res = await query({
    query: ME,
  })

  expect(res.data).not.toBeNull()
  expect(+res.data.me.id).toEqual(user.id)
})

test('it should throw an unauthorized error if there is no token', async () => {
  const user = await createUser()

  const { query } = await testClient()

  const res = await query({
    query: ME,
  })

  expect(res).toMatchSnapshot()
})

test('it should throw expired Token error', async () => {
  const user = await createUser()

  const { query } = await testClient({
    req: { headers: { authorization: 'Bearer ' + generateToken(user, -60) } },
  })

  const res = await query({
    query: ME,
  })

  expect(res).toMatchSnapshot()
})
```

*src/tests/queries/auth.queries.ts*
```typescript
export const ME = gql`
  query {
    me {
      id
      username
      email
    }
  }
`
```

I also discovered the **toMatchSnapshot()** method from jest ;). Very handy, but I feel that it is to be used with a lot of care ;). For example, in the test performed for a user registration, since we have *created_at* and *updated_at* fields that are different each time I run the test, my tests don't pass when I run the test again. So be sure that the answers will be exactly the same at each test launch before using this method. But I'll definitely have to read the jest doc in more details ;). 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/yrb5w2w8r4j8th9ljg11.png)

That's it for today. Don't forget to have a look at the Github repository too from time to time if you are interested in my articles because I don't necessarily detail everything ;). For example, I modified the knexfile.ts file to add environment variables, etc...

Bye and take care ;)