From 4ab3946181265ea21a4165ab3a43c32bb6658403 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 19 Mar 2018 15:22:33 +0100 Subject: [PATCH 1/9] Added testing variable, this uses :MEMORY: database when running tests. --- seasoned_api/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/package.json b/seasoned_api/package.json index a7a3720..383fea4 100644 --- a/seasoned_api/package.json +++ b/seasoned_api/package.json @@ -3,7 +3,7 @@ "main": "webserver/server.js", "scripts": { "start": "cross-env SEASONED_CONFIG=conf/development.json NODE_PATH=. node src/webserver/server.js", - "test": "cross-env SEASONED_CONFIG=conf/development.json NODE_PATH=. mocha --recursive test/system", + "test": "cross-env SEASONED_CONFIG=conf/development.json TESTING=true NODE_PATH=. mocha --recursive test/system", "coverage": "cross-env SEASONED_CONFIG=conf/test.json NODE_PATH=. istanbul cover -x script/autogenerate-documentation.js --include-all-sources --dir test/.coverage node_modules/mocha/bin/_mocha --recursive test/**/* -- --report lcovonly && cat test/.coverage/lcov.info | coveralls && rm -rf test/.coverage", "lint": "./node_modules/.bin/eslint src/" }, From e27d5c70840031ab79d2fec09a3f8ff6bce92ecb Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 19 Mar 2018 15:23:54 +0100 Subject: [PATCH 2/9] We use the db instance globally with establisheddatabase. --- seasoned_api/test/helpers/createCacheEntry.js | 3 +-- seasoned_api/test/helpers/createUser.js | 11 +++++------ seasoned_api/test/helpers/resetDatabase.js | 12 +++++------- 3 files changed, 11 insertions(+), 15 deletions(-) diff --git a/seasoned_api/test/helpers/createCacheEntry.js b/seasoned_api/test/helpers/createCacheEntry.js index afc7889..4a9f8b8 100644 --- a/seasoned_api/test/helpers/createCacheEntry.js +++ b/seasoned_api/test/helpers/createCacheEntry.js @@ -2,8 +2,7 @@ const Cache = require('src/tmdb/cache'); const SqliteDatabase = require('src/database/sqliteDatabase'); function createCacheEntry(key, value) { - const database = new SqliteDatabase(':memory:'); - const cache = new Cache(database); + const cache = new Cache(); return cache.set(key, value); } diff --git a/seasoned_api/test/helpers/createUser.js b/seasoned_api/test/helpers/createUser.js index 417d71d..a22f2a4 100644 --- a/seasoned_api/test/helpers/createUser.js +++ b/seasoned_api/test/helpers/createUser.js @@ -1,12 +1,11 @@ const User = require('src/user/user'); const UserSecurity = require('src/user/userSecurity'); -const SqliteDatabase = require('src/database/sqliteDatabase'); -function createUser(username, email, password) { - const database = new SqliteDatabase(':memory:'); - const userSecurity = new UserSecurity(database); - const user = new User(username, email); - return userSecurity.createNewUser(user, password); +function createUser(username, password) { + const userSecurity = new UserSecurity(); + const user = new User(username) + + return Promise.resolve(userSecurity.createNewUser(user, password)) } module.exports = createUser; \ No newline at end of file diff --git a/seasoned_api/test/helpers/resetDatabase.js b/seasoned_api/test/helpers/resetDatabase.js index fdb5c0b..d65bb97 100644 --- a/seasoned_api/test/helpers/resetDatabase.js +++ b/seasoned_api/test/helpers/resetDatabase.js @@ -1,11 +1,9 @@ -const SqliteDatabase = require('src/database/sqliteDatabase'); +const establishedDatabase = require('src/database/database'); -function resetDatabase() { - const database = new SqliteDatabase(':memory:'); - return Promise.resolve() - .then(() => database.connect()) - // .then(() => database.tearDown()) - .then(() => database.setUp()); +function resetDatabase() { + return Promise.resolve() + .then(() => establishedDatabase.tearDown()) + .then(() => establishedDatabase.setUp()) } module.exports = resetDatabase; From 9645fba4efe8305533d3e77872e31e2ee505c0ec Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 19 Mar 2018 15:24:42 +0100 Subject: [PATCH 3/9] Removed connect, connection is now a new sqlite instance, async run function, check for errors when executing and setup and teardown now return promises. --- seasoned_api/src/database/sqliteDatabase.js | 27 ++++++++++++--------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/seasoned_api/src/database/sqliteDatabase.js b/seasoned_api/src/database/sqliteDatabase.js index 10c2262..8923b00 100644 --- a/seasoned_api/src/database/sqliteDatabase.js +++ b/seasoned_api/src/database/sqliteDatabase.js @@ -3,10 +3,9 @@ const path = require('path'); const sqlite3 = require('sqlite3').verbose(); class SqliteDatabase { - constructor(host) { this.host = host; - this.connection = this.connect() + this.connection = new sqlite3.Database(this.host); this.schemaDirectory = path.join(__dirname, 'schemas'); } @@ -14,11 +13,11 @@ class SqliteDatabase { * Connect to the database. * @returns {Promise} succeeds if connection was established */ - connect() { - let database = new sqlite3.Database(this.host); - this.connection = database; - return database; - } + // connect() { + // let database = ; + // this.connection = database; + // return database; + // } /** * Run a SQL query against the database. @@ -26,7 +25,7 @@ class SqliteDatabase { * @param {Array} parameters in the SQL query * @returns {Promise} */ - run(sql, parameters) { + async run(sql, parameters) { return new Promise((resolve, reject) => { this.connection.run(sql, parameters, (error, result) => { if (error) @@ -78,7 +77,13 @@ class SqliteDatabase { */ async execute(sql) { return new Promise(resolve => { - resolve(this.connection.exec(sql)); + this.connection.exec(sql, (err, database) => { + if (err) { + console.log('ERROR: ', err); + reject(err); + } + resolve(); + }) }) } @@ -88,7 +93,7 @@ class SqliteDatabase { */ setUp() { const setupSchema = this.readSqlFile('setup.sql'); - return this.execute(setupSchema); + return Promise.resolve(this.execute(setupSchema)); } /** @@ -97,7 +102,7 @@ class SqliteDatabase { */ tearDown() { const tearDownSchema = this.readSqlFile('tearDown.sql'); - return this.execute(tearDownSchema); + return Promise.resolve(this.execute(tearDownSchema)); } /** From 559ef1bc1101c3edf366b4cc225590af65b82f44 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 19 Mar 2018 15:25:53 +0100 Subject: [PATCH 4/9] Before we create a db instance we check for testing flag is set and then use the :MEMORY: database for a anonymous db instance. --- seasoned_api/src/database/database.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/seasoned_api/src/database/database.js b/seasoned_api/src/database/database.js index b71c357..4497ee0 100644 --- a/seasoned_api/src/database/database.js +++ b/seasoned_api/src/database/database.js @@ -1,8 +1,8 @@ const configuration = require('src/config/configuration').getInstance(); const SqliteDatabase = require('src/database/sqliteDatabase'); -const database = new SqliteDatabase(configuration.get('database', 'host')); - +const host = process.env.TESTING ? ':memory:' : configuration.get('database', 'host'); +const database = new SqliteDatabase(host); /** * This module establishes a connection to the database * specified in the confgiuration file. It tries to setup @@ -10,7 +10,6 @@ const database = new SqliteDatabase(configuration.get('database', 'host')); * If the tables already exists, it simply proceeds. */ Promise.resolve() - .then(() => database.connect()) .then(() => database.setUp()); module.exports = database; From ed5d302820e84ee6c8e0e1f45f6185e8018226ac Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 19 Mar 2018 15:27:11 +0100 Subject: [PATCH 5/9] Stricter when running test, now we wait until resetdatabase and createuser are done in in the before function before running the tests. --- seasoned_api/test/system/asADeveloperIWantToLogin.js | 6 ++++-- seasoned_api/test/system/asAUserIWantToRequestAMovie.js | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/seasoned_api/test/system/asADeveloperIWantToLogin.js b/seasoned_api/test/system/asADeveloperIWantToLogin.js index 3a48e7a..c769c29 100644 --- a/seasoned_api/test/system/asADeveloperIWantToLogin.js +++ b/seasoned_api/test/system/asADeveloperIWantToLogin.js @@ -5,8 +5,10 @@ const createUser = require('test/helpers/createUser'); const resetDatabase = require('test/helpers/resetDatabase'); describe('As a user I want to log in', () => { - before(() => resetDatabase()); - before(() => createUser('test_user', 'test@gmail.com', 'password')); + before(() => { + return resetDatabase() + .then(() => createUser('test_user', 'password')) + }) it('should return 200 with a token if correct credentials are given', () => request(app) diff --git a/seasoned_api/test/system/asAUserIWantToRequestAMovie.js b/seasoned_api/test/system/asAUserIWantToRequestAMovie.js index f51c085..d78ceb4 100644 --- a/seasoned_api/test/system/asAUserIWantToRequestAMovie.js +++ b/seasoned_api/test/system/asAUserIWantToRequestAMovie.js @@ -5,8 +5,10 @@ const createUser = require('test/helpers/createUser'); const createToken = require('test/helpers/createToken'); describe('As a user I want to request a movie', () => { - before(() => resetDatabase()); - before(() => createUser('test_user', 'test@gmail.com', 'password')); + before(() => { + return resetDatabase() + .then(() => createUser('test_user', 'test@gmail.com', 'password')); + }) it('should return 200 when item is requested', () => request(app) From 424cf0985d27f1def2fce75fc166798834a24e01 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 19 Mar 2018 15:43:00 +0100 Subject: [PATCH 6/9] Added test for registering when user is already registered. --- ...GetErrorWhenRegisteringExistingUsername.js | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 seasoned_api/test/system/asAUserIWantToGetErrorWhenRegisteringExistingUsername.js diff --git a/seasoned_api/test/system/asAUserIWantToGetErrorWhenRegisteringExistingUsername.js b/seasoned_api/test/system/asAUserIWantToGetErrorWhenRegisteringExistingUsername.js new file mode 100644 index 0000000..0fd4557 --- /dev/null +++ b/seasoned_api/test/system/asAUserIWantToGetErrorWhenRegisteringExistingUsername.js @@ -0,0 +1,20 @@ +const assert = require('assert'); +const request = require('supertest-as-promised'); +const app = require('src/webserver/app'); +const createUser = require('test/helpers/createUser'); +const resetDatabase = require('test/helpers/resetDatabase'); + +describe('As a user I want error when registering existing username', () => { + before(() => { + return resetDatabase() + .then(() => createUser('test_user', 'password')) + }) + + it('should return 401 with error message when same username is given', () => + request(app) + .post('/api/v1/user') + .send({ username: 'test_user', password: 'password' }) + .expect(401) + .then(response => assert.equal(response.text, '{"success":false,"error":"That username is already registered"}')) + ); +}); From e092eae60ad73729dd5e0d261277495706789d83 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 19 Mar 2018 15:43:48 +0100 Subject: [PATCH 7/9] The retrieveHash and changePassword functions now return promises. --- seasoned_api/src/user/userRepository.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/seasoned_api/src/user/userRepository.js b/seasoned_api/src/user/userRepository.js index 4a6a148..f2f726a 100644 --- a/seasoned_api/src/user/userRepository.js +++ b/seasoned_api/src/user/userRepository.js @@ -35,10 +35,13 @@ class UserRepository { * @returns {Promise} */ retrieveHash(user) { - return this.database.get(this.queries.retrieveHash, user.username).then((row) => { - assert(row, 'The user does not exist.'); - return row.password; - }); + return Promise.resolve() + .then(() => this.database.get(this.queries.retrieveHash, user.username)) + .then((row) => { + assert(row, 'The user does not exist.'); + return row.password; + }) + .catch((err) => console.log('there was a error when getting hash', err)); } /** @@ -48,7 +51,7 @@ class UserRepository { * @returns {Promise} */ changePassword(user, password) { - return this.database.run(this.queries.change, [password, user.username]); + return Promise.resolve(this.database.run(this.queries.change, [password, user.username])); } checkAdmin(user) { From 8850f06e3e3da748b5a38fa4183ef5084c685912 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 19 Mar 2018 16:15:31 +0100 Subject: [PATCH 8/9] Updated travis config. --- .travis.yml | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6f664eb..f6cc463 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,11 @@ -{ - 'dist': 'trusty', - 'language': 'node_js', - 'node_js': '8.7.0', - 'cache': 'yarn', - 'scripts': [ - 'npm run test' - ], - 'before_install': [ - 'cd seasoned_api', - ], - 'before_script': 'yarn', - 'os': 'linux', -} +language: node_js +node_js: '8.7.0' +git: + submodules: false +script: + yarn test +before_install: + - cd seasoned_api +before_script: yarn +cache: false +os: linux From 40b7ceda5f1e54e540451571d81c39d7bdf31489 Mon Sep 17 00:00:00 2001 From: KevinMidboe Date: Mon, 19 Mar 2018 16:23:58 +0100 Subject: [PATCH 9/9] The name of the teardown.sql file was renamed, reverted to correct name. --- seasoned_api/src/database/sqliteDatabase.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/seasoned_api/src/database/sqliteDatabase.js b/seasoned_api/src/database/sqliteDatabase.js index 8923b00..e6b8bf7 100644 --- a/seasoned_api/src/database/sqliteDatabase.js +++ b/seasoned_api/src/database/sqliteDatabase.js @@ -101,7 +101,7 @@ class SqliteDatabase { * @returns {Promise} */ tearDown() { - const tearDownSchema = this.readSqlFile('tearDown.sql'); + const tearDownSchema = this.readSqlFile('teardown.sql'); return Promise.resolve(this.execute(tearDownSchema)); }