You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
demo-graphql-oauth/src/server/UserResolver.spec.ts

164 lines
5.5 KiB

import { gql } from "apollo-server-express"
import { createConnection, getConnection } from "typeorm"
import { callSchema } from "./schema"
import {
contextWithAuthHeader,
contextWithCookie,
initializeRollbackTransactions,
runInRollbackTransaction,
testingConnectionOptions,
} from "./testing"
import { signAccessToken, verifiedAccessTokenPayload } from "./UserResolver/auth"
import { User } from "./UserResolver/User"
describe("resolver of user", () => {
describe("createUser mutation should", () => {
it(
"return email and default token version as it creates user with mutation",
runInRollbackTransaction(async () => {
const response = await callSchema(createUserMutation)
expect(response.errors).toBeUndefined()
expect(response.data).toMatchObject({
createUser: {
email: "user-mutation@user-resolver.com",
},
})
})
)
})
describe("accessToken mutation should", () => {
it(
"return error for bad password or not-existent user",
runInRollbackTransaction(async () => {
const nonExistenUserResponse = await callSchema(
accessTokenMutation,
contextWithCookie()
)
await User.create({
email: "access-token@user-resolver.com",
password: "BAD-password",
}).save()
const badPasswordResponse = await callSchema(
accessTokenMutation,
contextWithCookie()
)
expect(nonExistenUserResponse.errors).not.toBeUndefined()
expect(nonExistenUserResponse.data).toBeNull()
expect(badPasswordResponse.errors).not.toBeUndefined()
expect(badPasswordResponse.data).toBeNull()
})
)
it(
"return a valid access token with expiry providing good credentials",
runInRollbackTransaction(async () => {
const oneMinute = 60
const sixteenMinutes = 60 * 16
const user = await User.create({
email: "access-token@user-resolver.com",
password: "password",
}).save()
const response = await callSchema(
accessTokenMutation,
contextWithCookie()
)
const accessToken: string = response.data!.accessToken
const jwtPayload = verifiedAccessTokenPayload(accessToken)
const jwtLifetime = jwtPayload.exp! - jwtPayload.iat!
expect(jwtLifetime).toBeGreaterThanOrEqual(oneMinute)
expect(jwtLifetime).not.toBeGreaterThan(sixteenMinutes)
expect(jwtPayload.uid).toBe(user.id)
expect(jwtPayload.msc).toBeLessThan(1000)
expect(response.errors).toBeUndefined()
})
)
})
describe("sign out mutation should", () => {
it(
"return true",
runInRollbackTransaction(async () => {
const response = await callSchema(signOutMutation, contextWithCookie())
expect(response.errors).toBeUndefined()
expect(response.data!.signOut).toBeTruthy()
})
)
})
describe("me mutation should", () => {
it(
"return an error without a valid access token",
runInRollbackTransaction(async () => {
const contextWithInvalidToken = contextWithAuthHeader(
"Bearer INVALID-TOKEN"
)
const response = await callSchema(meMutation, contextWithInvalidToken)
expect(response.errors).not.toBeUndefined()
expect(response.data).toBeNull()
})
)
it(
"return an user with a valid access token",
runInRollbackTransaction(async () => {
const user = await User.create({
email: "me-mutation@user-resolver.com",
}).save()
const contextWithValidToken = contextWithAuthHeader(
"Bearer " + signAccessToken({ uid: user.id, ver: user.tokenVersion })
)
const response = await callSchema(meMutation, contextWithValidToken)
expect(response.errors).toBeUndefined()
expect(response.data).toMatchObject({
me: { email: "me-mutation@user-resolver.com" },
})
})
)
})
})
beforeAll(async () => {
initializeRollbackTransactions()
await createConnection(testingConnectionOptions())
})
afterAll(async () => {
await getConnection().close()
})
const createUserMutation = gql`
mutation {
createUser(email: "user-mutation@user-resolver.com", password: "password") {
email
}
}
`
const accessTokenMutation = gql`
mutation {
accessToken(email: "access-token@user-resolver.com", password: "password")
}
`
const meMutation = gql`
mutation {
me {
email
}
}
`
const signOutMutation = gql`
mutation {
signOut
}
`