/*global describe, before, it, afterEach, beforeEach */ var fs = require('fs'); var path = require('path'); var util = require('util'); var events = require('events'); var assert = require('assert'); var proxyquire = require('proxyquire'); var generators = require('../'); var EventEmitter = require('events').EventEmitter; var win32 = process.platform === 'win32'; describe('yeoman.generators.Base', function () { before(generators.test.before(path.join(__dirname, 'temp'))); before(function () { function Dummy() { generators.Base.apply(this, arguments); } util.inherits(Dummy, generators.Base); Dummy.prototype.test = function () { this.shouldRun = true; }; var env = this.env = generators(); env.register(Dummy, 'dummy'); this.dummy = env.create('dummy'); this.fixtures = path.join(__dirname, 'fixtures'); }); it('generator.prompt(defaults, prompts, cb)', function (done) { this.dummy.prompt([], function () { done(); }); }); describe('generator.sourceRoot(root)', function () { it('should update the "_sourceRoot" property when root is given', function () { this.dummy.sourceRoot(this.fixtures); assert.equal(this.dummy._sourceRoot, this.fixtures); }); it('should return the updated or current value of "_sourceRoot"', function () { assert.equal(this.dummy.sourceRoot(), this.fixtures); }); }); describe('generator.destinationRoot(root)', function () { it('should update the "_destinationRoot" property when root is given', function () { this.dummy.destinationRoot('.'); assert.equal(this.dummy._destinationRoot, process.cwd()); }); it('should return the updated or current value of "_destinationRoot"', function () { assert.equal(this.dummy.destinationRoot(), process.cwd()); }); }); describe('generator.cacheRoot()', function () { it('should show the cache root where yeoman stores all temp files, on a platform that follows XDG', function () { process.env.XDG_CACHE_HOME = '.'; assert.equal(this.dummy.cacheRoot(), path.join(process.env.XDG_CACHE_HOME, 'yeoman')); }); it('should show the cache root where yeoman stores all temp files, on a plateform that doesn\'t follow XDG', function () { if (process.env.XDG_CACHE_HOME) { delete process.env.XDG_CACHE_HOME; } assert.equal(this.dummy.cacheRoot(), path.join(process.env[win32 ? 'USERPROFILE' : 'HOME'], '.cache/yeoman')); }); }); describe('generator.copy(source, destination, process)', function () { before(function (done) { this.dummy.copy(path.join(__dirname, 'fixtures/foo.js'), 'write/to/bar.js'); this.dummy.copy('foo.js', 'write/to/foo.js'); this.dummy.copy('foo-copy.js'); this.dummy.copy('yeoman-logo.png'); this.dummy.copy(path.join(__dirname, 'fixtures/lodash-copy.js'), 'write/to/lodash.js'); this.dummy.copy('foo-process.js', 'write/to/foo-process.js', function (contents, source, destination, props) { contents = contents.replace('foo', 'bar'); contents = contents.replace('\r\n', '\n'); return contents; }); this.dummy.conflicter.resolve(done); }); it('should copy source files relative to the "sourceRoot" value', function (done) { fs.stat('write/to/foo.js', done); }); it('should allow absolute path, and prevent the relative paths join', function (done) { fs.stat('write/to/bar.js', done); }); it('should allow to copy without using the templating (conficting with lodash/underscore)', function (done) { fs.stat('write/to/lodash.js', done); }); it('should default the destination to the source filepath value', function (done) { fs.stat('foo-copy.js', done); }); it('should retain executable mode on copied files', function (done) { fs.stat('write/to/bar.js', function (err, stats) { assert(stats.mode & 1 === 1, 'File should be executable.'); done(); }); }); it('should process source contents via function', function (done) { fs.readFile('write/to/foo-process.js', function (err, data) { if (err) throw err; assert.equal(data, 'var bar = \'foo\';\n'); done(); }); }); it('should not give a conflict on same binary files', function (done) { this.dummy.conflicter.force = true; this.dummy.conflicter.collision('yeoman-logo.png', fs.readFileSync(path.join(this.fixtures, 'yeoman-logo.png')), function (status) { assert.equal(status, 'identical'); this.dummy.conflicter.force = false; done(); }.bind(this)); }); }); describe('generator.read(filepath, encoding)', function () { it('should read files relative to the "sourceRoot" value', function () { var body = this.dummy.read('foo.js'); assert.equal(body, 'var foo = \'foo\';' + '\n'); }); it('should allow absolute path, and prevent the relative paths join', function () { var body = this.dummy.read(path.join(__dirname, 'fixtures/foo.js')); assert.equal(body, 'var foo = \'foo\';' + '\n'); }); }); describe('generator.write(filepath, content)', function () { before(function (done) { this.body = 'var bar = \'bar\';' + '\n'; this.dummy.write('write/to/foobar.js', this.body); this.dummy.conflicter.resolve(done); }); it('should write the specified files relative to the "destinationRoot" value', function (done) { var body = this.body; fs.readFile('write/to/foobar.js', 'utf8', function (err, actual) { if (err) { return done(err); } assert.ok(actual, body); done(); }); }); }); describe('generator.template(source, destination, data)', function () { before(function (done) { this.dummy.foo = 'fooooooo'; this.dummy.template('foo-template.js', 'write/to/from-template.js'); this.dummy.template('foo-template.js'); this.dummy.template('foo-template.js', 'write/to/from-template-bar.js', { foo: 'bar' }); this.dummy.template('foo-template.js', 'write/to/from-template.js'); this.dummy.conflicter.resolve(done); }); it('should copy and process source file to destination', function (done) { fs.stat('write/to/from-template.js', done); }); it('should defaults the destination to the source filepath value, relative to "destinationRoot" value', function () { var body = fs.readFileSync('foo-template.js', 'utf8'); assert.equal(body, 'var fooooooo = \'fooooooo\';' + '\n'); }); it('should process underscore templates with the passed-in data', function () { var body = fs.readFileSync('write/to/from-template-bar.js', 'utf8'); assert.equal(body, 'var bar = \'bar\';' + '\n'); }); it('should process underscore templates with the actual generator instance, when no data is given', function () { var body = fs.readFileSync('write/to/from-template.js', 'utf8'); assert.equal(body, 'var fooooooo = \'fooooooo\';' + '\n'); }); }); describe('generator.directory(source, destination, process)', function () { before(function (done) { // avoid hitting conflict state in this configuration for now if (fs.existsSync('foo.js')) { fs.unlinkSync('foo.js'); } // avoid hitting conflict state in this configuration for now if (fs.existsSync('foo-template.js')) { fs.unlinkSync('foo-template.js'); } // avoid hitting conflict state in this configuration for now if (fs.existsSync('yeoman-logo.png')) { fs.unlinkSync('yeoman-logo.png'); } this.dummy.directory('./', 'directory'); this.dummy.directory('./'); this.dummy.directory('./', 'directory-processed', function (contents, source, destination, props) { if (source.indexOf('foo-process.js') !== -1) { contents = contents.replace('foo', 'bar'); contents = contents.replace('\r\n', '\n'); } return contents; }); this.dummy.conflicter.resolve(done); }); it('should copy and process source files to destination', function (done) { fs.stat('directory/foo-template.js', function (err) { if (err) { return done(err); } fs.stat('directory/foo.js', done); }); }); it('should defaults the destination to the source filepath value, relative to "destinationRoot" value', function (done) { fs.stat('foo-template.js', function (err) { if (err) { return done(err); } fs.stat('foo.js', done); }); }); it('should process underscore templates with the actual generator instance', function () { var body = fs.readFileSync('directory/foo-template.js', 'utf8'); var foo = this.dummy.foo; assert.equal(body, 'var ' + foo + ' = \'' + foo + '\';\n'); }); it('should process source contents via function', function () { var body = fs.readFileSync('directory-processed/foo-process.js', 'utf8'); assert.equal(body, 'var bar = \'foo\';\n'); }); }); describe('actions/install', function () { var asyncStub = { on: function (key, cb) { if (key === 'exit') { cb(); } return asyncStub; } }; describe('generator.bowerInstall', function () { beforeEach(function () { // Keep track of all commands executed by spawnCommand. this.commandsRun = []; this.dummy.spawnCommand = function spawnCommand(cmd, args) { this.commandsRun.push([cmd, args]); return asyncStub; }.bind(this); }); afterEach(function () { // Restore the original function. var spawn = require('../lib/actions/spawn_command'); this.dummy._.extend(this.dummy, spawn); }); it('should spawn a bower process', function (done) { this.dummy.bowerInstall(null, done); assert(this.commandsRun.length, 1); assert.deepEqual(this.commandsRun[0], ['bower', ['install']]); }); it('should spawn a bower process with formatted options', function (done) { this.dummy.bowerInstall('jquery', { saveDev: true }, done); assert(this.commandsRun.length, 1); assert.deepEqual(this.commandsRun[0], ['bower', ['install', 'jquery', '--save-dev']]); }); }); describe('generator.installDependencies', function () { beforeEach(function () { // Keep track of all commands executed by spawnCommand. this.commandsRun = []; this.dummy.spawnCommand = function spawnCommand(cmd, args) { this.commandsRun.push(cmd); return asyncStub; }.bind(this); }); afterEach(function () { // Restore the original function. var spawn = require('../lib/actions/spawn_command'); this.dummy._.extend(this.dummy, spawn); }); it('should spawn npm and bower', function () { this.dummy.installDependencies(); assert.deepEqual(this.commandsRun, ['bower', 'npm']); }); it('should not spawn anything with skipInstall', function () { this.dummy.installDependencies({ skipInstall: true }); assert.deepEqual(this.commandsRun.length, 0); }); it('npmInstall should run without callback', function () { this.dummy.npmInstall('yo', { save: true }); assert.deepEqual(this.commandsRun.length, 1); }); it('should execute a callback after installs', function () { var called = false; this.dummy.installDependencies({ callback: function () { called = true; } }); assert.deepEqual(this.commandsRun, ['bower', 'npm']); assert(called); }); it('should accept and execute a function as its only argument', function () { var called = false; this.dummy.installDependencies(function () { called = true; }); assert.deepEqual(this.commandsRun, ['bower', 'npm']); assert(called); }); }); }); describe('generator.expandFiles', function () { before(function (done) { this.dummy.copy('foo.js', 'write/abc/abc.js'); this.dummy.conflicter.resolve(done); }); it('should return expand files', function () { var files = this.dummy.expandFiles('write/abc/**'); assert.deepEqual(files, ['write/abc/abc.js']); }); it('should return expand files', function () { var files = this.dummy.expandFiles('abc/**', {cwd: './write'}); assert.deepEqual(files, ['abc/abc.js']); }); }); });