From 3179ab49b7a2d6cc48f6c1ef624746371c655f99 Mon Sep 17 00:00:00 2001
From: Roland Bernard <rolbernard@unibz.it>
Date: Sun, 23 May 2021 20:23:26 +0200
Subject: [PATCH] Added tests for the auth.ts file

---
 server/package.json        |   2 +-
 server/src/setupTests.ts   |   4 +-
 server/src/v1/auth.test.ts | 225 ++++++++++++++++++++++++++++++++++++-
 server/src/v1/auth.ts      |  41 +++----
 server/src/v1/user.test.ts |   7 +-
 5 files changed, 245 insertions(+), 34 deletions(-)

diff --git a/server/package.json b/server/package.json
index 3abc8c5..728f81a 100644
--- a/server/package.json
+++ b/server/package.json
@@ -23,7 +23,7 @@
     "scripts": {
         "start": "nodemon src/index.ts",
         "build": "tsc --project .",
-        "test": "jest --passWithNoTests --config ./jest.config.json"
+        "test": "jest --passWithNoTests --verbose --config ./jest.config.json"
     },
     "devDependencies": {
         "@types/bcrypt": "^3.0.1",
diff --git a/server/src/setupTests.ts b/server/src/setupTests.ts
index fd33e1e..4329df1 100644
--- a/server/src/setupTests.ts
+++ b/server/src/setupTests.ts
@@ -8,14 +8,14 @@ async function loadTestData() {
         .insert([
             {
                 id: '00000000-0000-0000-0000-000000000000',
-                user_name: 'User0',
+                user_name: 'user0',
                 passwd_hash: '$2b$10$sjHhJNz4sLNclKEwWISZRe4cVju6jn4QjMVs4wdZ6wug2SKG774pq',
                 email: 'test0@example.com',
                 real_name: 'Testing Tester',
                 image: null,
             }, {
                 id: '00000000-0000-0000-0000-000000000001',
-                user_name: 'User1',
+                user_name: 'user1',
                 passwd_hash: '$2b$10$sjHhJNz4sLNclKEwWISZRe4cVju6jn4QjMVs4wdZ6wug2SKG774pq',
                 email: 'test1@example.com',
                 real_name: 'Tester Testing',
diff --git a/server/src/v1/auth.test.ts b/server/src/v1/auth.test.ts
index d87a33a..fb67e4e 100644
--- a/server/src/v1/auth.test.ts
+++ b/server/src/v1/auth.test.ts
@@ -1,11 +1,232 @@
 
-import supertest from 'supertest';
+import supertest, { Response } from 'supertest';
 
+import { database } from '../database';
 import { api } from '../api';
+import { generateAuthToken } from './auth';
 
 const request = supertest(api);
 
-test('', async () => {
+describe('requesting a token', () => {
+    test('fails if username does not exist', async () => {
+        const response = await request
+            .post('/v1/auth/token')
+            .send({
+                username: 'User2',
+                password: 'testtest',
+            });
+        expect(response.status).toEqual(404);
+        expect(response.body.status).toEqual('error');
+    });
+
+    test('fails if the password is wrong', async () => {
+        const response = await request
+            .post('/v1/auth/token')
+            .send({
+                username: 'User0',
+                password: 'test',
+            });
+        expect(response.status).toEqual(403);
+        expect(response.body.status).toEqual('error');
+    });
+
+    test('succeeds if username and password are correct', async () => {
+        const response = await request
+            .post('/v1/auth/token')
+            .send({
+                username: 'User0',
+                password: 'testtest',
+            });
+        expect(response.status).toEqual(200);
+        expect(response.body.status).toEqual('success');
+        expect(response.body.token).toBeTruthy();
+    });
+});
+
+test('registering a user with an existing username fails', async () => {
+    const response = await request
+        .post('/v1/auth/register')
+        .send({
+            username: 'User0',
+            password: 'testtest',
+        });
+    expect(response.status).toEqual(400);
+    expect(response.body.status).toEqual('error');
+});
+
+describe('successful user registration', () => {
+    let response: Response;
+
+    beforeAll(async () => {
+        response = await request
+            .post('/v1/auth/register')
+            .send({
+                username: 'User2',
+                password: 'testing',
+                email: 'test@example.com',
+                realname: 'Real Test',
+            });
+    });
+
+    test('returns a valid token', async () => {
+        expect(response.status).toEqual(200);
+        expect(response.body.status).toEqual('success');
+        expect(response.body.token).toBeTruthy();
+    });
+
+    test('creates a new user', async () => {
+        const user = await database('users')
+            .select()
+            .where({ 'users.user_name': 'user2' });
+        expect(user.length).toEqual(1);
+        expect(user[0].user_name).toEqual('user2');
+        expect(user[0].email).toEqual('test@example.com');
+        expect(user[0].real_name).toEqual('Real Test');
+    });
+
+    test('auth token can be requested', async () => {
+        const response = await request
+            .post('/v1/auth/token')
+            .send({
+                username: 'User2',
+                password: 'testing',
+            });
+        expect(response.status).toEqual(200);
+        expect(response.body.status).toEqual('success');
+        expect(response.body.token).toBeTruthy();
+    });
+
+    afterAll(async () => {
+        await database('users')
+            .delete()
+            .where({ 'users.user_name': 'user2' });
+    });
+})
+
+describe('password can be changed', () => {
+    let response: Response;
+
+    beforeAll(async () => {
+        response = await request
+            .put('/v1/auth/password')
+            .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-0000-0000-000000000000')}`)
+            .send({
+                password: 'testtest2',
+            });
+    })
+    
+    test('returns successfully', async () => {
+        expect(response.status).toEqual(200);
+        expect(response.body.status).toEqual('success');
+    });
+    
+    test('token request with old password fails', async () => {
+        const response = await request
+            .post('/v1/auth/token')
+            .send({
+                username: 'User0',
+                password: 'testtest',
+            });
+        expect(response.status).toEqual(403);
+        expect(response.body.status).toEqual('error');
+    });
     
+    test('token request with new password succeeds', async () => {
+        const response = await request
+            .post('/v1/auth/token')
+            .send({
+                username: 'User0',
+                password: 'testtest2',
+            });
+        expect(response.status).toEqual(200);
+        expect(response.body.status).toEqual('success');
+        expect(response.body.token).toBeTruthy();
+    });
+
+    afterAll(async () => {
+        response = await request
+            .put('/v1/auth/password')
+            .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-0000-0000-000000000000')}`)
+            .send({
+                password: 'testtest',
+            });
+    })
+});
+
+test('changing username to an existing one fails', async () => {
+    const response = await request
+        .put('/v1/auth/username')
+        .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-0000-0000-000000000000')}`)
+        .send({
+            username: 'User1',
+        });
+    expect(response.status).toEqual(400);
+    expect(response.body.status).toEqual('error');
+});
+
+describe('username can be changed', () => {
+    let response: Response;
+
+    beforeAll(async () => {
+        response = await request
+            .put('/v1/auth/username')
+            .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-0000-0000-000000000000')}`)
+            .send({
+                username: 'User00',
+            });
+    })
+    
+    test('returns successfully', async () => {
+        expect(response.status).toEqual(200);
+        expect(response.body.status).toEqual('success');
+    });
+    
+    test('token request with old username fails', async () => {
+        const response = await request
+            .post('/v1/auth/token')
+            .send({
+                username: 'User0',
+                password: 'testtest',
+            });
+        expect(response.status).toEqual(404);
+        expect(response.body.status).toEqual('error');
+    });
+    
+    test('token request with new username succeeds', async () => {
+        const response = await request
+            .post('/v1/auth/token')
+            .send({
+                username: 'User00',
+                password: 'testtest',
+            });
+        expect(response.status).toEqual(200);
+        expect(response.body.status).toEqual('success');
+        expect(response.body.token).toBeTruthy();
+    });
+
+    afterAll(async () => {
+        response = await request
+            .put('/v1/auth/username')
+            .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-0000-0000-000000000000')}`)
+            .send({
+                username: 'User0',
+            });
+    })
+});
+
+test('valid tokens can be extended', async () => {
+    const response = await request
+        .get('/v1/auth/extend')
+        .set('Authorization', `Bearer ${await generateAuthToken('00000000-0000-0000-0000-000000000000')}`);
+    expect(response.status).toEqual(200);
+    expect(response.body.status).toEqual('success');
+});
+
+test('invalid tokens cause an 403 error', async () => {
+    const response = await request
+        .get('/v1/auth/extend')
+        .set('Authorization', 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjAwMDAwMDAwLTAwMDAtMDAwMC0wMDAwLTAwMDAwMDAwMDAwMCJ9.Kq2cI42E_-c1No89CpGyqwLV3BL4fFpe5fGhDjrUr2c');
+    expect(response.status).toEqual(403);
+    expect(response.body.status).toEqual('error');
 });
 
diff --git a/server/src/v1/auth.ts b/server/src/v1/auth.ts
index 4bf7400..93a92cb 100644
--- a/server/src/v1/auth.ts
+++ b/server/src/v1/auth.ts
@@ -65,7 +65,7 @@ export function requireVerification(req: Request, res: Response, next: NextFunct
     }
 }
 
-async function generateAuthToken(id: string) {
+export async function generateAuthToken(id: string) {
     const token: Token = {
         id: id,
         type: authTokenType,
@@ -90,31 +90,24 @@ auth.post('/register', async (req, res) => {
         const id = uuid();
         const passwdHash = await hash(body.password, 10);
         const name = body.username.trim().toLowerCase();
-        if (name.length >= 4) {
-            try {
-                const token = await generateAuthToken(id);
-                await database('users').insert({
-                    id: id,
-                    user_name: name,
-                    passwd_hash: passwdHash,
-                    email: body.email ?? null,
-                    real_name: body.realname ?? null,
-                });
-                res.status(200).json({
-                    status: 'success',
-                    token: token,
-                });
-            } catch (e) {
-                // Fails if unique constraint for username is not met
-                res.status(400).json({
-                    status: 'error',
-                    message: 'failed to create user',
-                });
-            }
-        } else {
+        try {
+            const token = await generateAuthToken(id);
+            await database('users').insert({
+                id: id,
+                user_name: name,
+                passwd_hash: passwdHash,
+                email: body.email ?? null,
+                real_name: body.realname ?? null,
+            });
+            res.status(200).json({
+                status: 'success',
+                token: token,
+            });
+        } catch (e) {
+            // Fails if unique constraint for username is not met
             res.status(400).json({
                 status: 'error',
-                message: 'usernames must be four letters or longer',
+                message: 'failed to create user',
             });
         }
     } else {
diff --git a/server/src/v1/user.test.ts b/server/src/v1/user.test.ts
index 269ea75..5587d6e 100644
--- a/server/src/v1/user.test.ts
+++ b/server/src/v1/user.test.ts
@@ -6,11 +6,8 @@ import { api } from '../api';
 const request = supertest(api);
 
 test('non existant username returns 404 for /v1/user/name/', async () => {
-    const response = await request.get('/v1/user/name/__NO_REAL_NAME__');
+    const response = await request.get('/v1/user/name/User3');
     expect(response.status).toEqual(404);
-    expect(response.body).toEqual({
-        status: 'error',
-        message: 'user not found',
-    });
+    expect(response.body.status).toEqual('error');
 });
 
-- 
GitLab