From 0b5cfd933f353b6c6e8813c83c3f7656ab356ffc Mon Sep 17 00:00:00 2001 From: kirrg001 Date: Thu, 15 Feb 2018 20:14:30 +0100 Subject: [PATCH] Added knex mock for unit testing no issue - added https://github.com/colonyamerican/mock-knex as dev dependency - the mock serves our data generator test data by default - but you can define your own if you want - we need a proper mock for unit testing - we should not mock bookshelf if possible, otherwise we can't test event flows --- core/test/utils/mocks/index.js | 1 + core/test/utils/mocks/knex.js | 131 +++++++++++++++++++++++++++++++++ package.json | 1 + yarn.lock | 12 +++ 4 files changed, 145 insertions(+) create mode 100644 core/test/utils/mocks/knex.js diff --git a/core/test/utils/mocks/index.js b/core/test/utils/mocks/index.js index c18aae5c90..0faa205023 100644 --- a/core/test/utils/mocks/index.js +++ b/core/test/utils/mocks/index.js @@ -1,2 +1,3 @@ exports.utils = require('./utils'); exports.express = require('./express'); +exports.knex = require('./knex'); diff --git a/core/test/utils/mocks/knex.js b/core/test/utils/mocks/knex.js new file mode 100644 index 0000000000..152ecb8879 --- /dev/null +++ b/core/test/utils/mocks/knex.js @@ -0,0 +1,131 @@ +'use strict'; + +const mockKnex = require('mock-knex'), + _ = require('lodash'), + DataGenerator = require('../fixtures/data-generator'), + knex = require('../../../server/data/db').knex; + +/** + * Knex mock. The database is our Datagenerator. + * You can either self register queries or you simply rely on the data generator data. + * + * Please extend if you use-case does not work. + */ +class KnexMock { + initialiseDb() { + this.db = {}; + + _.each(_.pick(DataGenerator.Content, ['posts', 'users', 'tags', 'permissions', 'roles']), (objects, tableName) => { + this.db[tableName] = []; + + _.each(objects, (object) => { + const lookup = { + users: DataGenerator.forKnex.createUser, + posts: DataGenerator.forKnex.createPost, + tags: DataGenerator.forKnex.createTag, + permissions: DataGenerator.forKnex.createPermission, + roles: DataGenerator.forKnex.createRole, + }; + + this.db[tableName].push(lookup[tableName](object)); + }); + }); + } + + mock(options) { + options = options || {autoMock: true}; + mockKnex.mock(knex); + + this.initialiseDb(); + + this.tracker = mockKnex.getTracker(); + this.tracker.install(); + + if (options.autoMock) { + this.tracker.on('query', (query) => { + if (query.method === 'select') { + if (query.bindings.length && query.sql.match(/where/)) { + query.sql = query.sql.replace(/`/g, '"'); + + const tableName = query.sql.match(/from\s\"(\w+)\"/)[1], + where = query.sql.match(/\"(\w+)\"\s\=\s\?/)[1], + value = query.bindings[0], + dbEntry = _.find(this.db[tableName], ((existing) => { + if (existing[where] === value) { + return true; + } + })); + + if (dbEntry) { + query.response([dbEntry]); + } else { + query.response([]); + } + } + } else if (query.method === 'insert') { + query.sql = query.sql.replace(/`/g, '"'); + + const tableName = query.sql.match(/into\s\"(\w+)\"/)[1]; + let keys = query.sql.match(/\(([^)]+)\)/)[1], + entry = {}; + + keys = keys.replace(/"/g, ''); + keys = keys.replace(/\s/g, ''); + keys = keys.split(','); + + _.each(keys, (key, index) => { + entry[key] = query.bindings[index]; + }); + + if (!this.db[tableName]) { + this.db[tableName] = []; + } + + this.db[tableName].push(entry); + query.response(entry); + } else if (query.method === 'update') { + query.sql = query.sql.replace(/`/g, '"'); + + const tableName = query.sql.match(/update\s\"(\w+)\"/)[1], + where = query.sql.match(/where\s\"(\w+)\"\s\=\s\?/)[1], + value = query.bindings.slice(-1)[0], + dbEntry = _.find(this.db[tableName], ((existing) => { + if (existing[where] === value) { + return true; + } + })); + + if (!dbEntry) { + query.reject(new Error('not found')); + } else { + let keys = query.sql.match(/set(.*)where/)[1], + entry = {}; + + keys = keys.match(/\"\w+\"/g).join(','); + keys = keys.replace(/"/g, ''); + keys = keys.replace(/\s/g, ''); + keys = keys.split(','); + + _.each(keys, (key, index) => { + entry[key] = query.bindings[index]; + dbEntry[key] = entry[key]; + }); + + query.response(entry); + } + } else { + query.reject(new Error('not implemented.')); + } + }); + } + + return this.tracker; + } + + unmock() { + this.tracker.uninstall(); + mockKnex.unmock(knex); + } +} + +module.exports = KnexMock; diff --git a/package.json b/package.json index 2e3064ec4b..daf7934313 100644 --- a/package.json +++ b/package.json @@ -120,6 +120,7 @@ "matchdep": "2.0.0", "minimist": "1.2.0", "mocha": "4.1.0", + "mock-knex": "0.4.0", "nock": "9.1.6", "rewire": "3.0.2", "should": "13.2.1", diff --git a/yarn.lock b/yarn.lock index 78fad44c1f..fc2a1eeb28 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3690,6 +3690,10 @@ lodash@^3.10.1, lodash@~3.10.1: version "3.10.1" resolved "https://registry.yarnpkg.com/lodash/-/lodash-3.10.1.tgz#5bf45e8e49ba4189e17d482789dfd15bd140b7b6" +lodash@^4.14.2: + version "4.17.5" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.5.tgz#99a92d65c0272debe8c96b6057bc8fbfa3bed511" + lodash@~0.9.2: version "0.9.2" resolved "https://registry.yarnpkg.com/lodash/-/lodash-0.9.2.tgz#8f3499c5245d346d682e5b0d3b40767e09f1a92c" @@ -4041,6 +4045,14 @@ mocha@^3.1.2: mkdirp "0.5.1" supports-color "3.1.2" +mock-knex@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/mock-knex/-/mock-knex-0.4.0.tgz#32c4ed97ff7cf9c86eca2400902f34e1f7f88de1" + dependencies: + bluebird "^3.4.1" + lodash "^4.14.2" + semver "^5.3.0" + moment-timezone@0.5.14: version "0.5.14" resolved "https://registry.yarnpkg.com/moment-timezone/-/moment-timezone-0.5.14.tgz#4eb38ff9538b80108ba467a458f3ed4268ccfcb1"