Comparing version 2.1.0 to 2.2.0
@@ -228,2 +228,3 @@ 'use strict'; | ||
mm(this.context, 'assertCSRF', () => {}); | ||
mm(this.context, 'assertCsrf', () => {}); | ||
return this; | ||
@@ -230,0 +231,0 @@ }, |
2.2.0 / 2017-01-25 | ||
================== | ||
* feat: reimplement mm.app (#22) | ||
2.1.0 / 2017-01-16 | ||
@@ -3,0 +8,0 @@ ================== |
152
lib/app.js
'use strict'; | ||
const path = require('path'); | ||
const debug = require('debug')('mm'); | ||
const rimraf = require('rimraf'); | ||
const is = require('is-type-of'); | ||
const sleep = require('ko-sleep'); | ||
const co = require('co'); | ||
const ready = require('get-ready'); | ||
const EventEmitter = require('events'); | ||
const formatOptions = require('./format_options'); | ||
const apps = new Map(); | ||
const INIT = Symbol('init'); | ||
const MOCK_APP_METHOD = [ | ||
'ready', | ||
'_ready', | ||
'_readyCallbacks', | ||
'closed', | ||
'close', | ||
'on', | ||
'once', | ||
]; | ||
class MockApplication extends EventEmitter { | ||
constructor(options) { | ||
super(); | ||
this.options = options; | ||
this.isReady = false; | ||
this.closed = false; | ||
ready.mixin(this); | ||
co(this[INIT].bind(this)) | ||
.then(() => { | ||
this.isReady = true; | ||
this.ready(true); | ||
}) | ||
.catch(err => this.emit('error', err)); | ||
} | ||
* [INIT]() { | ||
const egg = require(this.options.customEgg); | ||
const Agent = egg.Agent; | ||
const agent = this.agent = new Agent(this.options); | ||
yield agent.ready(); | ||
const Application = egg.Application; | ||
const app = this.app = new Application(this.options); | ||
yield app.ready(); | ||
} | ||
close() { | ||
this.closed = true; | ||
return Promise.all([ | ||
this.agent.close(), | ||
this.app.close(), | ||
]).then(() => sleep(1000)); | ||
} | ||
} | ||
module.exports = function(options) { | ||
@@ -27,4 +77,25 @@ options = formatOptions(options); | ||
const agent = getAgent(options); | ||
const app = getApp(Object.assign({}, options, { agent })); | ||
let app = new MockApplication(options); | ||
app = new Proxy(app, { | ||
get(target, prop) { | ||
// don't delegate properties on MockApplication | ||
if (MOCK_APP_METHOD.includes(prop)) { | ||
return getProperty(target, prop); | ||
} | ||
// it's asyncrounus when agent and app are loading, | ||
// so should get the properties after loader ready | ||
if (target.isReady) { | ||
return getProperty(target.app, prop); | ||
} | ||
throw new Error(`can't get ${prop} before ready`); | ||
}, | ||
set(target, prop, value) { | ||
if (MOCK_APP_METHOD.includes(prop)) return true; | ||
if (target.isReady) { | ||
target.app[prop] = value; | ||
return true; | ||
} | ||
throw new Error(`can't set ${prop} before ready`); | ||
}, | ||
}); | ||
@@ -35,73 +106,8 @@ apps.set(options.baseDir, app); | ||
function getApp(options) { | ||
debug('getApp from customEgg: %s', options.customEgg); | ||
const egg = require(options.customEgg); | ||
const MockApplication = extendsEggApplication(egg, options); | ||
return new MockApplication(options); | ||
} | ||
function getAgent(options) { | ||
debug('getAgent from customEgg: %s', options.customEgg); | ||
const egg = require(options.customEgg); | ||
const agent = new egg.Agent(options); | ||
return agent; | ||
} | ||
function extendsEggApplication(egg, options) { | ||
const symbol = egg.symbol || {}; | ||
// load after agent ready | ||
class MockApplication extends egg.Application { | ||
constructor(options) { | ||
super(options); | ||
this.closed = false; | ||
this.on('error', onerror); | ||
this.ready(() => this.removeListener('error', onerror)); | ||
this.messenger = options.agent.messenger; | ||
this.agent = options.agent; | ||
this.agent.ready(this.readyCallback('agent_ready')); | ||
} | ||
get [symbol.Loader]() { | ||
const CustomLoader = super[Symbol.for('egg#loader')] || super[symbol.Loader]; | ||
const self = this; | ||
class MockLoader extends CustomLoader { | ||
load() { | ||
// catch agent's error, send it to app | ||
const done = self.readyCallback('loader.load'); | ||
options.agent.ready().then(() => { | ||
super.load(); | ||
done(); | ||
}).catch(done); | ||
} | ||
} | ||
return MockLoader; | ||
} | ||
get [Symbol.for('egg#loader')]() { | ||
return this[symbol.Loader]; | ||
} | ||
get [Symbol.for('egg#eggPath')]() { | ||
return path.join(__dirname, '..'); | ||
} | ||
close() { | ||
this.closed = true; | ||
return Promise.all([ | ||
super.close(), | ||
this.agent.close(), | ||
]).then(() => sleep(1000)); | ||
} | ||
function getProperty(target, prop) { | ||
const member = target[prop]; | ||
if (is.function(member)) { | ||
return member.bind(target); | ||
} | ||
return MockApplication; | ||
return member; | ||
} | ||
function onerror(err) { | ||
console.error(err); | ||
console.error(err.stack); | ||
} |
{ | ||
"name": "egg-mock", | ||
"version": "2.1.0", | ||
"version": "2.2.0", | ||
"eggPlugin": { | ||
@@ -25,2 +25,3 @@ "name": "egg-mock" | ||
"dependencies": { | ||
"co": "^4.6.0", | ||
"coffee": "^3.3.0", | ||
@@ -33,3 +34,3 @@ "debug": "^2.6.0", | ||
"merge-descriptors": "^1.0.1", | ||
"mm": "^2.0.0", | ||
"mm": "^2.0.1", | ||
"rimraf": "^2.5.4" | ||
@@ -39,6 +40,6 @@ }, | ||
"autod": "^2.7.1", | ||
"egg": "^0.7.0", | ||
"egg-bin": "^1.10.0", | ||
"egg": "^0.9.0", | ||
"egg-bin": "^2.0.2", | ||
"egg-ci": "^1.1.0", | ||
"eslint": "^3.13.1", | ||
"eslint": "^3.14.0", | ||
"eslint-config-egg": "^3.2.0", | ||
@@ -45,0 +46,0 @@ "ko-sleep": "^1.0.2", |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
31156
766
11
10