UNPKG

injectr

Version:

Finally, a solution to node.js dependency injection

196 lines (192 loc) 8.37 kB
"use strict"; var expect = require("expect.js"), injectr = require("../lib/injectr"), pretendr = require("pretendr"); describe("injectr", function () { beforeEach(function () { this.mockFs = pretendr({ readFileSync : function () {} }); this.mockPath = pretendr({ join : function () {}, dirname : function () {} }); this.mockPath.join.returnValue('dir/filename'); this.mockVm = pretendr({ createScript : function () {} }); this.mockVm.createScript.template({ runInNewContext : function () {}, runInThisContext : function () {} }); this.mockCoffeeScript = pretendr({ compile : function () {} }); // this.injectr is the injectr under test // the injectr var is being used to test it this.injectr = injectr('../lib/injectr.js', { fs : this.mockFs.mock, path : this.mockPath.mock, vm : this.mockVm.mock, 'coffee-script' : this.mockCoffeeScript.mock }, { module : { parent : module } }); }); it("should attempt to resolve the selected file", function () { this.mockPath.dirname.returnValue('dirname'); this.injectr('./filename'); expect(this.mockPath.dirname.calls).to.have.length(1); expect(this.mockPath.dirname.calls[0].args) .to.have.property(0, __filename); expect(this.mockPath.join.calls).to.have.length(1); expect(this.mockPath.join.calls[0].args) .to.have.property(0, 'dirname') .and.to.have.property(1, './filename'); }); it("should read in the selected file", function () { this.injectr('filename'); expect(this.mockFs.readFileSync.calls).to.have.length(1); expect(this.mockFs.readFileSync.calls[0].args) .to.have.property(0, 'dir/filename') .and.to.have.property(1, 'utf8'); }); it("should only read the file once per file", function () { this.mockFs.readFileSync.returnValue('dummy'); this.injectr('filename'); this.injectr('filename'); expect(this.mockFs.readFileSync.calls).to.have.length(1); this.mockPath.join.returnValue('dir/filename2'); this.injectr('filename2'); this.injectr('filename2'); expect(this.mockFs.readFileSync.calls).to.have.length(2); }); it("should create a script from the file", function () { var call; this.mockFs.readFileSync.returnValue('dummy script'); this.injectr('filename'); expect(this.mockVm.createScript.calls).to.have.length(1); call = this.mockVm.createScript.calls[0]; expect(call.args[0]).to.equal('dummy script'); expect(call.args[1]).to.equal('dir/filename'); }); it("should run the script in a new context", function () { var mockScript; this.injectr('filename'); mockScript = this.mockVm.createScript.calls[0].pretendr; expect(mockScript.runInNewContext.calls).to.have.length(1); }); it("should have a predefined module.exports", function () { var context, mockScript; this.injectr('filename'); mockScript = this.mockVm.createScript.calls[0].pretendr; context = mockScript.runInNewContext.calls[0].args[0]; expect(context).to.have.property('module'); expect(context.module).to.have.property('exports'); expect(context.module.exports).to.be.an('object'); }); it("should have an exports property equal to module.exports", function () { var context, mockScript; this.injectr('filename'); mockScript = this.mockVm.createScript.calls[0].pretendr; context = mockScript.runInNewContext.calls[0].args[0]; expect(context).to.have.property('exports', context.module.exports); }); it("should return module.exports", function () { var context, mockScript, l; l = this.injectr('filename'); mockScript = this.mockVm.createScript.calls[0].pretendr; context = mockScript.runInNewContext.calls[0].args[0]; expect(l).to.equal(context.module.exports); }); it("should allow an onload callback", function () { var mockCb = pretendr(function () {}); this.mockFs.readFileSync.returnValue('before'); mockCb.returnValue('after'); this.injectr.onload = mockCb.mock; this.injectr('filename'); expect(mockCb.calls).to.have.length(1); expect(mockCb.calls[0].args).to.have.property(0, 'dir/filename') .and.to.have.property(1, 'before'); expect(this.mockVm.createScript.calls[0].args[0]).to.equal('after'); }); it("should only run the callback once per file", function () { var mockCb = pretendr(function () {}); mockCb.returnValue('dummy'); this.injectr.onload = mockCb.mock; this.injectr('filename'); this.injectr('filename'); expect(mockCb.calls).to.have.length(1); }); it("should use the provided context to run the script", function () { var context = {}, mockScript; this.injectr('filename', null, context); mockScript = this.mockVm.createScript.calls[0].pretendr; expect(mockScript.runInNewContext.calls[0].args[0]) .to.equal(context); }); it("should still have module and require objects", function () { var context = {}; this.injectr('filename', null, context); expect(context).to.have.property('module') .and.to.have.property('require'); }); describe("#require", function () { it("should get mock libraries if provided", function () { var context, customLib = {}, mockScript; this.injectr('filename', { customLib : customLib }); mockScript = this.mockVm.createScript.calls[0].pretendr; context = mockScript.runInNewContext.calls[0].args[0]; expect(context.require('customLib')).to.equal(customLib); }); it("should require libraries otherwise", function () { var context, mockScript; this.injectr('filename', {}); mockScript = this.mockVm.createScript.calls[0].pretendr; context = mockScript.runInNewContext.calls[0].args[0]; expect(JSON.stringify(context.require('fs'))) .to.eql(JSON.stringify(require('fs'))); }); it("should resolve directories to the injectr'd file", function () { var args, l, mockScript, req; l = this.injectr('filename'); mockScript = this.mockVm.createScript.calls[0].pretendr; req = mockScript.runInNewContext.calls[0].args[0].require; this.mockPath.dirname.returnValue('/directory/'); this.mockPath.join.returnValue('fs'); req('./a-local-module'); args = this.mockPath.dirname.calls[1].args; expect(args).to.have.property(0, 'dir/filename'); args = this.mockPath.join.calls[1].args; expect(args[0]).to.equal('/directory/'); expect(args[1]).to.equal('./a-local-module'); expect(JSON.stringify(l)).to.equal(JSON.stringify(require('fs'))); }); it("should compile coffee-script files before running", function () { var out; this.mockCoffeeScript.compile.returnValue('compiled'); out = this.injectr.onload('file.coffee', 'uncompiled'); expect(out).to.equal('compiled'); this.mockCoffeeScript.compile.returnValue('another compiled'); out = this.injectr.onload('another.coffee', ''); expect(out).to.equal('another compiled'); out = this.injectr.onload('non-coffee', 'javascript'); expect(out).to.equal('javascript'); }); }); });