import { GraphQLClient } from 'graphql-request' import Factory from '../../seed/factories' import { host } from '../../jest/helpers' import { getDriver } from '../../bootstrap/neo4j' import { createPasswordReset } from './passwordReset' const factory = Factory() let client const driver = getDriver() const getAllPasswordResets = async () => { const session = driver.session() let transactionRes = await session.run('MATCH (r:PasswordReset) RETURN r') const resets = transactionRes.records.map(record => record.get('r')) session.close() return resets } describe('passwordReset', () => { beforeEach(async () => { client = new GraphQLClient(host) await factory.create('User', { email: 'user@example.org', role: 'user', password: '1234', }) }) afterEach(async () => { await factory.cleanDatabase() }) describe('requestPasswordReset', () => { const mutation = `mutation($email: String!) { requestPasswordReset(email: $email) }` describe('with invalid email', () => { const variables = { email: 'non-existent@example.org' } it('resolves anyways', async () => { await expect(client.request(mutation, variables)).resolves.toEqual({ requestPasswordReset: true, }) }) it('creates no node', async () => { await client.request(mutation, variables) const resets = await getAllPasswordResets() expect(resets).toHaveLength(0) }) }) describe('with a valid email', () => { const variables = { email: 'user@example.org' } it('resolves', async () => { await expect(client.request(mutation, variables)).resolves.toEqual({ requestPasswordReset: true, }) }) it('creates node with label `PasswordReset`', async () => { await client.request(mutation, variables) const resets = await getAllPasswordResets() expect(resets).toHaveLength(1) }) it('creates a reset code', async () => { await client.request(mutation, variables) const resets = await getAllPasswordResets() const [reset] = resets const { code } = reset.properties expect(code).toHaveLength(6) }) }) }) describe('resetPassword', () => { const setup = async (options = {}) => { const { email = 'user@example.org', issuedAt = new Date(), code = 'abcdef', } = options const session = driver.session() await createPasswordReset({ driver, email, issuedAt, code }) session.close() } const mutation = `mutation($code: String!, $email: String!, $newPassword: String!) { resetPassword(code: $code, email: $email, newPassword: $newPassword) }` let email = 'user@example.org' let code = 'abcdef' let newPassword = 'supersecret' let variables describe('invalid email', () => { it('resolves to false', async () => { await setup() variables = { newPassword, email: 'non-existent@example.org', code } await expect(client.request(mutation, variables)).resolves.toEqual({ resetPassword: false }) }) }) describe('valid email', () => { describe('but invalid code', () => { it('resolves to false', async () => { await setup() variables = { newPassword, email, code: 'slkdjf' } await expect(client.request(mutation, variables)).resolves.toEqual({ resetPassword: false, }) }) }) describe('and valid code', () => { beforeEach(() => { variables = { newPassword, email: 'user@example.org', code: 'abcdef', } }) describe('and code not expired', () => { beforeEach(async () => { await setup() }) it('resolves to true', async () => { await expect(client.request(mutation, variables)).resolves.toEqual({ resetPassword: true, }) }) it('updates PasswordReset `usedAt` property', async () => { await client.request(mutation, variables) const requests = await getAllPasswordResets() const [request] = requests const { usedAt } = request.properties expect(usedAt).not.toBeFalsy() }) it('updates password of the user', async () => { await client.request(mutation, variables) const checkLoginMutation = ` mutation($email: String!, $password: String!) { login(email: $email, password: $password) } ` const expected = expect.objectContaining({ login: expect.any(String) }) await expect( client.request(checkLoginMutation, { email: 'user@example.org', password: 'supersecret', }), ).resolves.toEqual(expected) }) }) describe('but expired code', () => { beforeEach(async () => { const issuedAt = new Date() issuedAt.setDate(issuedAt.getDate() - 1) await setup({ issuedAt }) }) it('resolves to false', async () => { await expect(client.request(mutation, variables)).resolves.toEqual({ resetPassword: false, }) }) it('does not update PasswordReset `usedAt` property', async () => { await client.request(mutation, variables) const requests = await getAllPasswordResets() const [request] = requests const { usedAt } = request.properties expect(usedAt).toBeUndefined() }) }) }) }) }) })