symlinks.js
  1  var path = require('path');
  2  var fs = require('fs');
  3  var test = require('tape');
  4  var map = require('array.prototype.map');
  5  var resolve = require('../');
  6  
  7  var symlinkDir = path.join(__dirname, 'resolver', 'symlinked', 'symlink');
  8  var packageDir = path.join(__dirname, 'resolver', 'symlinked', '_', 'node_modules', 'package');
  9  var modADir = path.join(__dirname, 'symlinks', 'source', 'node_modules', 'mod-a');
 10  var symlinkModADir = path.join(__dirname, 'symlinks', 'dest', 'node_modules', 'mod-a');
 11  try {
 12      fs.unlinkSync(symlinkDir);
 13  } catch (err) {}
 14  try {
 15      fs.unlinkSync(packageDir);
 16  } catch (err) {}
 17  try {
 18      fs.unlinkSync(modADir);
 19  } catch (err) {}
 20  try {
 21      fs.unlinkSync(symlinkModADir);
 22  } catch (err) {}
 23  
 24  try {
 25      fs.symlinkSync('./_/symlink_target', symlinkDir, 'dir');
 26  } catch (err) {
 27      // if fails then it is probably on Windows and lets try to create a junction
 28      fs.symlinkSync(path.join(__dirname, 'resolver', 'symlinked', '_', 'symlink_target') + '\\', symlinkDir, 'junction');
 29  }
 30  try {
 31      fs.symlinkSync('../../package', packageDir, 'dir');
 32  } catch (err) {
 33      // if fails then it is probably on Windows and lets try to create a junction
 34      fs.symlinkSync(path.join(__dirname, '..', '..', 'package') + '\\', packageDir, 'junction');
 35  }
 36  try {
 37      fs.symlinkSync('../../source/node_modules/mod-a', symlinkModADir, 'dir');
 38  } catch (err) {
 39      // if fails then it is probably on Windows and lets try to create a junction
 40      fs.symlinkSync(path.join(__dirname, '..', '..', 'source', 'node_modules', 'mod-a') + '\\', symlinkModADir, 'junction');
 41  }
 42  
 43  test('symlink', function (t) {
 44      t.plan(2);
 45  
 46      resolve('foo', { basedir: symlinkDir, preserveSymlinks: false }, function (err, res, pkg) {
 47          t.error(err);
 48          t.equal(res, path.join(__dirname, 'resolver', 'symlinked', '_', 'node_modules', 'foo.js'));
 49      });
 50  });
 51  
 52  test('sync symlink when preserveSymlinks = true', function (t) {
 53      t.plan(4);
 54  
 55      resolve('foo', { basedir: symlinkDir }, function (err, res, pkg) {
 56          t.ok(err, 'there is an error');
 57          t.notOk(res, 'no result');
 58  
 59          t.equal(err && err.code, 'MODULE_NOT_FOUND', 'error code matches require.resolve');
 60          t.equal(
 61              err && err.message,
 62              'Cannot find module \'foo\' from \'' + symlinkDir + '\'',
 63              'can not find nonexistent module'
 64          );
 65      });
 66  });
 67  
 68  test('sync symlink', function (t) {
 69      var start = new Date();
 70      t.doesNotThrow(function () {
 71          t.equal(
 72              resolve.sync('foo', { basedir: symlinkDir, preserveSymlinks: false }),
 73              path.join(__dirname, 'resolver', 'symlinked', '_', 'node_modules', 'foo.js')
 74          );
 75      });
 76      t.ok(new Date() - start < 50, 'resolve.sync timedout');
 77      t.end();
 78  });
 79  
 80  test('sync symlink when preserveSymlinks = true', function (t) {
 81      t.throws(function () {
 82          resolve.sync('foo', { basedir: symlinkDir });
 83      }, /Cannot find module 'foo'/);
 84      t.end();
 85  });
 86  
 87  test('sync symlink from node_modules to other dir when preserveSymlinks = false', function (t) {
 88      var basedir = path.join(__dirname, 'resolver', 'symlinked', '_');
 89      var fn = resolve.sync('package', { basedir: basedir, preserveSymlinks: false });
 90  
 91      t.equal(fn, path.resolve(__dirname, 'resolver/symlinked/package/bar.js'));
 92      t.end();
 93  });
 94  
 95  test('async symlink from node_modules to other dir when preserveSymlinks = false', function (t) {
 96      t.plan(2);
 97      var basedir = path.join(__dirname, 'resolver', 'symlinked', '_');
 98      resolve('package', { basedir: basedir, preserveSymlinks: false }, function (err, result) {
 99          t.notOk(err, 'no error');
100          t.equal(result, path.resolve(__dirname, 'resolver/symlinked/package/bar.js'));
101      });
102  });
103  
104  test('packageFilter', function (t) {
105      function relative(x) {
106          return path.relative(__dirname, x);
107      }
108  
109      function testPackageFilter(preserveSymlinks) {
110          return function (st) {
111              st.plan('is 1.x' ? 3 : 5); // eslint-disable-line no-constant-condition
112  
113              var destMain = 'symlinks/dest/node_modules/mod-a/index.js';
114              var destPkg = 'symlinks/dest/node_modules/mod-a/package.json';
115              var sourceMain = 'symlinks/source/node_modules/mod-a/index.js';
116              var sourcePkg = 'symlinks/source/node_modules/mod-a/package.json';
117              var destDir = path.join(__dirname, 'symlinks', 'dest');
118  
119              /* eslint multiline-comment-style: 0 */
120              /* v2.x will restore these tests
121              var packageFilterPath = [];
122              var actualPath = resolve.sync('mod-a', {
123                  basedir: destDir,
124                  preserveSymlinks: preserveSymlinks,
125                  packageFilter: function (pkg, pkgfile, dir) {
126                      packageFilterPath.push(pkgfile);
127                  }
128              });
129              st.equal(
130                  relative(actualPath),
131                  path.normalize(preserveSymlinks ? destMain : sourceMain),
132                  'sync: actual path is correct'
133              );
134              st.deepEqual(
135                  map(packageFilterPath, relative),
136                  map(preserveSymlinks ? [destPkg, destPkg] : [sourcePkg, sourcePkg], path.normalize),
137                  'sync: packageFilter pkgfile arg is correct'
138              );
139              */
140  
141              var asyncPackageFilterPath = [];
142              resolve(
143                  'mod-a',
144                  {
145                      basedir: destDir,
146                      preserveSymlinks: preserveSymlinks,
147                      packageFilter: function (pkg, pkgfile) {
148                          asyncPackageFilterPath.push(pkgfile);
149                      }
150                  },
151                  function (err, actualPath) {
152                      st.error(err, 'no error');
153                      st.equal(
154                          relative(actualPath),
155                          path.normalize(preserveSymlinks ? destMain : sourceMain),
156                          'async: actual path is correct'
157                      );
158                      st.deepEqual(
159                          map(asyncPackageFilterPath, relative),
160                          map(
161                              preserveSymlinks ? [destPkg, destPkg, destPkg] : [sourcePkg, sourcePkg, sourcePkg],
162                              path.normalize
163                          ),
164                          'async: packageFilter pkgfile arg is correct'
165                      );
166                  }
167              );
168          };
169      }
170  
171      t.test('preserveSymlinks: false', testPackageFilter(false));
172  
173      t.test('preserveSymlinks: true', testPackageFilter(true));
174  
175      t.end();
176  });