1 | /**
|
2 | * Collection of unit test helpers. (mostly related to Mocha syntax)
|
3 | * @module test/helpers
|
4 | */
|
5 |
|
6 | ;
|
7 | var fs = require('fs');
|
8 | var path = require('path');
|
9 | var _ = require('lodash');
|
10 | var rimraf = require('rimraf');
|
11 | var mkdirp = require('mkdirp');
|
12 | var yeoman = require('yeoman-environment');
|
13 | var Generator = require('yeoman-generator');
|
14 | var adapter = require('./adapter');
|
15 |
|
16 | /**
|
17 | * Create a function that will clean up the test directory,
|
18 | * cd into it, and create a dummy gruntfile inside. Intended for use
|
19 | * as a callback for the mocha `before` hook.
|
20 | *
|
21 | * @param {String} dir - path to the test directory
|
22 | * @returns {Function} mocha callback
|
23 | */
|
24 |
|
25 | exports.setUpTestDirectory = function(dir) {
|
26 | return function(done) {
|
27 | exports.testDirectory(dir, function() {
|
28 | exports.gruntfile({ dummy: true }, done);
|
29 | });
|
30 | };
|
31 | };
|
32 |
|
33 | /**
|
34 | *
|
35 | * Generates a new Gruntfile.js in the current working directory based on
|
36 | * options hash passed in.
|
37 | *
|
38 | * @param {Object} options - Grunt configuration
|
39 | * @param {Function} done - callback to call on completion
|
40 | * @example
|
41 | * before(helpers.gruntfile({
|
42 | * foo: {
|
43 | * bar: '<config.baz>'
|
44 | * }
|
45 | * }));
|
46 | *
|
47 | */
|
48 |
|
49 | exports.gruntfile = function(options, done) {
|
50 | var config = 'grunt.initConfig(' + JSON.stringify(options, null, 2) + ');';
|
51 |
|
52 | config = config
|
53 | .split('\n')
|
54 | .map(function(line) {
|
55 | return ' ' + line;
|
56 | })
|
57 | .join('\n');
|
58 |
|
59 | var out = ['module.exports = function (grunt) {', config, '};'];
|
60 |
|
61 | fs.writeFile('Gruntfile.js', out.join('\n'), done);
|
62 | };
|
63 |
|
64 | /**
|
65 | * Clean-up the test directory and cd into it.
|
66 | * Call given callback after entering the test directory.
|
67 | * @param {String} dir - path to the test directory
|
68 | * @param {Function} cb - callback executed after setting working directory to dir
|
69 | * @example
|
70 | * testDirectory(path.join(__dirname, './temp'), function () {
|
71 | * fs.writeFileSync('testfile', 'Roses are red.');
|
72 | * });
|
73 | */
|
74 |
|
75 | exports.testDirectory = function(dir, cb) {
|
76 | if (!dir) {
|
77 | throw new Error('Missing directory');
|
78 | }
|
79 |
|
80 | dir = path.resolve(dir);
|
81 |
|
82 | // Make sure we're not deleting CWD by moving to top level folder. As we `cd` in the
|
83 | // test dir after cleaning up, this shouldn't be perceivable.
|
84 | process.chdir('/');
|
85 |
|
86 | rimraf(dir, function(err) {
|
87 | if (err) {
|
88 | return cb(err);
|
89 | }
|
90 |
|
91 | mkdirp.sync(dir);
|
92 | process.chdir(dir);
|
93 | cb();
|
94 | });
|
95 | };
|
96 |
|
97 | /**
|
98 | * Answer prompt questions for the passed-in generator
|
99 | * @param {Generator} generator - a Yeoman generator
|
100 | * @param {Object} answers - an object where keys are the
|
101 | * generators prompt names and values are the answers to
|
102 | * the prompt questions
|
103 | * @example
|
104 | * mockPrompt(angular, {'bootstrap': 'Y', 'compassBoostrap': 'Y'});
|
105 | */
|
106 |
|
107 | exports.mockPrompt = function(generator, answers, callback) {
|
108 | var promptModule = generator.env.adapter.promptModule;
|
109 | answers = answers || {};
|
110 | var DummyPrompt = adapter.DummyPrompt;
|
111 |
|
112 | Object.keys(promptModule.prompts).forEach(function(name) {
|
113 | promptModule.registerPrompt(name, DummyPrompt.bind(DummyPrompt, answers, callback));
|
114 | });
|
115 | };
|
116 |
|
117 | /**
|
118 | * Restore defaults prompts on a generator.
|
119 | * @param {Generator} generator
|
120 | */
|
121 | exports.restorePrompt = function(generator) {
|
122 | generator.env.adapter.promptModule.restoreDefaultPrompts();
|
123 | };
|
124 |
|
125 | /**
|
126 | * Provide mocked values to the config
|
127 | * @param {Generator} generator - a Yeoman generator
|
128 | * @param {Object} localConfig - localConfig - should look just like if called config.getAll()
|
129 | */
|
130 | exports.mockLocalConfig = function(generator, localConfig) {
|
131 | generator.config.defaults(localConfig);
|
132 | };
|
133 |
|
134 | /**
|
135 | * Create a simple, dummy generator
|
136 | */
|
137 |
|
138 | exports.createDummyGenerator = () =>
|
139 | class extends Generator {
|
140 | test() {
|
141 | this.shouldRun = true;
|
142 | }
|
143 | };
|
144 |
|
145 | /**
|
146 | * Create a generator, using the given dependencies and controller arguments
|
147 | * Dependecies can be path (autodiscovery) or an array [<generator>, <name>]
|
148 | *
|
149 | * @param {String} name - the name of the generator
|
150 | * @param {Array} dependencies - paths to the generators dependencies
|
151 | * @param {Array|String} args - arguments to the generator;
|
152 | * if String, will be split on spaces to create an Array
|
153 | * @param {Object} options - configuration for the generator
|
154 | * @param {Boolean} [localConfigOnly=true] - passes localConfigOnly to the generators
|
155 | * @example
|
156 | * var deps = ['../../app',
|
157 | * '../../common',
|
158 | * '../../controller',
|
159 | * '../../main',
|
160 | * [createDummyGenerator(), 'testacular:app']
|
161 | * ];
|
162 | * var angular = createGenerator('angular:app', deps);
|
163 | */
|
164 |
|
165 | exports.createGenerator = function(
|
166 | name,
|
167 | dependencies,
|
168 | args,
|
169 | options,
|
170 | localConfigOnly = true
|
171 | ) {
|
172 | var env = yeoman.createEnv([], { sharedOptions: { localConfigOnly } });
|
173 | this.registerDependencies(env, dependencies);
|
174 |
|
175 | return env.create(name, { arguments: args, options: options });
|
176 | };
|
177 |
|
178 | /**
|
179 | * Register a list of dependent generators into the provided env.
|
180 | * Dependecies can be path (autodiscovery) or an array [<generator>, <name>]
|
181 | *
|
182 | * @param {Array} dependencies - paths to the generators dependencies
|
183 | */
|
184 |
|
185 | exports.registerDependencies = function(env, dependencies) {
|
186 | dependencies.forEach(function(dependency) {
|
187 | if (_.isArray(dependency)) {
|
188 | env.registerStub.apply(env, dependency);
|
189 | } else {
|
190 | env.register(dependency);
|
191 | }
|
192 | });
|
193 | };
|
194 |
|
195 | /**
|
196 | * Creates a test environment.
|
197 | *
|
198 | * @param {Function} envContructor - environment constructor method.
|
199 | * @param {Boolean} [localConfigOnly=true] - passes localConfigOnly option to the generators
|
200 | * @returns {Object} environment instance
|
201 | * const env = setupEnv(require('yeoman-environment').createEnv);
|
202 | */
|
203 |
|
204 | exports.createTestEnv = function(
|
205 | envContructor = yeoman.createEnv,
|
206 | localConfigOnly = true
|
207 | ) {
|
208 | return envContructor(
|
209 | [],
|
210 | { sharedOptions: { localConfigOnly } },
|
211 | new adapter.TestAdapter()
|
212 | );
|
213 | };
|
214 |
|
215 | /**
|
216 | * Run the provided Generator
|
217 | * @param {String|Function} GeneratorOrNamespace - Generator constructor or namespace
|
218 | * @return {RunContext}
|
219 | */
|
220 |
|
221 | exports.run = function(GeneratorOrNamespace, settings) {
|
222 | var RunContext = require('./run-context');
|
223 | return new RunContext(GeneratorOrNamespace, settings);
|
224 | };
|