mock.js
  1  var path = require('path');
  2  var test = require('tape');
  3  var resolve = require('../');
  4  
  5  test('mock', function (t) {
  6      t.plan(8);
  7  
  8      var files = {};
  9      files[path.resolve('/foo/bar/baz.js')] = 'beep';
 10  
 11      var dirs = {};
 12      dirs[path.resolve('/foo/bar')] = true;
 13  
 14      function opts(basedir) {
 15          return {
 16              basedir: path.resolve(basedir),
 17              isFile: function (file, cb) {
 18                  cb(null, Object.prototype.hasOwnProperty.call(files, path.resolve(file)));
 19              },
 20              isDirectory: function (dir, cb) {
 21                  cb(null, !!dirs[path.resolve(dir)]);
 22              },
 23              readFile: function (file, cb) {
 24                  cb(null, files[path.resolve(file)]);
 25              },
 26              realpath: function (file, cb) {
 27                  cb(null, file);
 28              }
 29          };
 30      }
 31  
 32      resolve('./baz', opts('/foo/bar'), function (err, res, pkg) {
 33          if (err) return t.fail(err);
 34          t.equal(res, path.resolve('/foo/bar/baz.js'));
 35          t.equal(pkg, undefined);
 36      });
 37  
 38      resolve('./baz.js', opts('/foo/bar'), function (err, res, pkg) {
 39          if (err) return t.fail(err);
 40          t.equal(res, path.resolve('/foo/bar/baz.js'));
 41          t.equal(pkg, undefined);
 42      });
 43  
 44      resolve('baz', opts('/foo/bar'), function (err, res) {
 45          t.equal(err.message, "Cannot find module 'baz' from '" + path.resolve('/foo/bar') + "'");
 46          t.equal(err.code, 'MODULE_NOT_FOUND');
 47      });
 48  
 49      resolve('../baz', opts('/foo/bar'), function (err, res) {
 50          t.equal(err.message, "Cannot find module '../baz' from '" + path.resolve('/foo/bar') + "'");
 51          t.equal(err.code, 'MODULE_NOT_FOUND');
 52      });
 53  });
 54  
 55  test('mock from package', function (t) {
 56      t.plan(8);
 57  
 58      var files = {};
 59      files[path.resolve('/foo/bar/baz.js')] = 'beep';
 60  
 61      var dirs = {};
 62      dirs[path.resolve('/foo/bar')] = true;
 63  
 64      function opts(basedir) {
 65          return {
 66              basedir: path.resolve(basedir),
 67              isFile: function (file, cb) {
 68                  cb(null, Object.prototype.hasOwnProperty.call(files, file));
 69              },
 70              isDirectory: function (dir, cb) {
 71                  cb(null, !!dirs[path.resolve(dir)]);
 72              },
 73              'package': { main: 'bar' },
 74              readFile: function (file, cb) {
 75                  cb(null, files[file]);
 76              },
 77              realpath: function (file, cb) {
 78                  cb(null, file);
 79              }
 80          };
 81      }
 82  
 83      resolve('./baz', opts('/foo/bar'), function (err, res, pkg) {
 84          if (err) return t.fail(err);
 85          t.equal(res, path.resolve('/foo/bar/baz.js'));
 86          t.equal(pkg && pkg.main, 'bar');
 87      });
 88  
 89      resolve('./baz.js', opts('/foo/bar'), function (err, res, pkg) {
 90          if (err) return t.fail(err);
 91          t.equal(res, path.resolve('/foo/bar/baz.js'));
 92          t.equal(pkg && pkg.main, 'bar');
 93      });
 94  
 95      resolve('baz', opts('/foo/bar'), function (err, res) {
 96          t.equal(err.message, "Cannot find module 'baz' from '" + path.resolve('/foo/bar') + "'");
 97          t.equal(err.code, 'MODULE_NOT_FOUND');
 98      });
 99  
100      resolve('../baz', opts('/foo/bar'), function (err, res) {
101          t.equal(err.message, "Cannot find module '../baz' from '" + path.resolve('/foo/bar') + "'");
102          t.equal(err.code, 'MODULE_NOT_FOUND');
103      });
104  });
105  
106  test('mock package', function (t) {
107      t.plan(2);
108  
109      var files = {};
110      files[path.resolve('/foo/node_modules/bar/baz.js')] = 'beep';
111      files[path.resolve('/foo/node_modules/bar/package.json')] = JSON.stringify({
112          main: './baz.js'
113      });
114  
115      var dirs = {};
116      dirs[path.resolve('/foo')] = true;
117      dirs[path.resolve('/foo/node_modules')] = true;
118  
119      function opts(basedir) {
120          return {
121              basedir: path.resolve(basedir),
122              isFile: function (file, cb) {
123                  cb(null, Object.prototype.hasOwnProperty.call(files, path.resolve(file)));
124              },
125              isDirectory: function (dir, cb) {
126                  cb(null, !!dirs[path.resolve(dir)]);
127              },
128              readFile: function (file, cb) {
129                  cb(null, files[path.resolve(file)]);
130              },
131              realpath: function (file, cb) {
132                  cb(null, file);
133              }
134          };
135      }
136  
137      resolve('bar', opts('/foo'), function (err, res, pkg) {
138          if (err) return t.fail(err);
139          t.equal(res, path.resolve('/foo/node_modules/bar/baz.js'));
140          t.equal(pkg && pkg.main, './baz.js');
141      });
142  });
143  
144  test('mock package from package', function (t) {
145      t.plan(2);
146  
147      var files = {};
148      files[path.resolve('/foo/node_modules/bar/baz.js')] = 'beep';
149      files[path.resolve('/foo/node_modules/bar/package.json')] = JSON.stringify({
150          main: './baz.js'
151      });
152  
153      var dirs = {};
154      dirs[path.resolve('/foo')] = true;
155      dirs[path.resolve('/foo/node_modules')] = true;
156  
157      function opts(basedir) {
158          return {
159              basedir: path.resolve(basedir),
160              isFile: function (file, cb) {
161                  cb(null, Object.prototype.hasOwnProperty.call(files, path.resolve(file)));
162              },
163              isDirectory: function (dir, cb) {
164                  cb(null, !!dirs[path.resolve(dir)]);
165              },
166              'package': { main: 'bar' },
167              readFile: function (file, cb) {
168                  cb(null, files[path.resolve(file)]);
169              },
170              realpath: function (file, cb) {
171                  cb(null, file);
172              }
173          };
174      }
175  
176      resolve('bar', opts('/foo'), function (err, res, pkg) {
177          if (err) return t.fail(err);
178          t.equal(res, path.resolve('/foo/node_modules/bar/baz.js'));
179          t.equal(pkg && pkg.main, './baz.js');
180      });
181  });
182  
183  test('symlinked', function (t) {
184      t.plan(4);
185  
186      var files = {};
187      files[path.resolve('/foo/bar/baz.js')] = 'beep';
188      files[path.resolve('/foo/bar/symlinked/baz.js')] = 'beep';
189  
190      var dirs = {};
191      dirs[path.resolve('/foo/bar')] = true;
192      dirs[path.resolve('/foo/bar/symlinked')] = true;
193  
194      function opts(basedir) {
195          return {
196              preserveSymlinks: false,
197              basedir: path.resolve(basedir),
198              isFile: function (file, cb) {
199                  cb(null, Object.prototype.hasOwnProperty.call(files, path.resolve(file)));
200              },
201              isDirectory: function (dir, cb) {
202                  cb(null, !!dirs[path.resolve(dir)]);
203              },
204              readFile: function (file, cb) {
205                  cb(null, files[path.resolve(file)]);
206              },
207              realpath: function (file, cb) {
208                  var resolved = path.resolve(file);
209  
210                  if (resolved.indexOf('symlinked') >= 0) {
211                      cb(null, resolved);
212                      return;
213                  }
214  
215                  var ext = path.extname(resolved);
216  
217                  if (ext) {
218                      var dir = path.dirname(resolved);
219                      var base = path.basename(resolved);
220                      cb(null, path.join(dir, 'symlinked', base));
221                  } else {
222                      cb(null, path.join(resolved, 'symlinked'));
223                  }
224              }
225          };
226      }
227  
228      resolve('./baz', opts('/foo/bar'), function (err, res, pkg) {
229          if (err) return t.fail(err);
230          t.equal(res, path.resolve('/foo/bar/symlinked/baz.js'));
231          t.equal(pkg, undefined);
232      });
233  
234      resolve('./baz.js', opts('/foo/bar'), function (err, res, pkg) {
235          if (err) return t.fail(err);
236          t.equal(res, path.resolve('/foo/bar/symlinked/baz.js'));
237          t.equal(pkg, undefined);
238      });
239  });
240  
241  test('readPackage', function (t) {
242      t.plan(3);
243  
244      var files = {};
245      files[path.resolve('/foo/node_modules/bar/something-else.js')] = 'beep';
246      files[path.resolve('/foo/node_modules/bar/package.json')] = JSON.stringify({
247          main: './baz.js'
248      });
249      files[path.resolve('/foo/node_modules/bar/baz.js')] = 'boop';
250  
251      var dirs = {};
252      dirs[path.resolve('/foo')] = true;
253      dirs[path.resolve('/foo/node_modules')] = true;
254  
255      function opts(basedir) {
256          return {
257              basedir: path.resolve(basedir),
258              isFile: function (file, cb) {
259                  cb(null, Object.prototype.hasOwnProperty.call(files, path.resolve(file)));
260              },
261              isDirectory: function (dir, cb) {
262                  cb(null, !!dirs[path.resolve(dir)]);
263              },
264              'package': { main: 'bar' },
265              readFile: function (file, cb) {
266                  cb(null, files[path.resolve(file)]);
267              },
268              realpath: function (file, cb) {
269                  cb(null, file);
270              }
271          };
272      }
273  
274      t.test('with readFile', function (st) {
275          st.plan(3);
276  
277          resolve('bar', opts('/foo'), function (err, res, pkg) {
278              st.error(err);
279              st.equal(res, path.resolve('/foo/node_modules/bar/baz.js'));
280              st.equal(pkg && pkg.main, './baz.js');
281          });
282      });
283  
284      var readPackage = function (readFile, file, cb) {
285          var barPackage = path.join('bar', 'package.json');
286          if (file.slice(-barPackage.length) === barPackage) {
287              cb(null, { main: './something-else.js' });
288          } else {
289              cb(null, JSON.parse(files[path.resolve(file)]));
290          }
291      };
292  
293      t.test('with readPackage', function (st) {
294          st.plan(3);
295  
296          var options = opts('/foo');
297          delete options.readFile;
298          options.readPackage = readPackage;
299          resolve('bar', options, function (err, res, pkg) {
300              st.error(err);
301              st.equal(res, path.resolve('/foo/node_modules/bar/something-else.js'));
302              st.equal(pkg && pkg.main, './something-else.js');
303          });
304      });
305  
306      t.test('with readFile and readPackage', function (st) {
307          st.plan(1);
308  
309          var options = opts('/foo');
310          options.readPackage = readPackage;
311          resolve('bar', options, function (err) {
312              st.throws(function () { throw err; }, TypeError, 'errors when both readFile and readPackage are provided');
313          });
314      });
315  });