readdirp.js 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /*jshint asi:true */
  2. var test = require('tap').test
  3. , path = require('path')
  4. , fs = require('fs')
  5. , util = require('util')
  6. , net = require('net')
  7. , readdirp = require('../readdirp.js')
  8. , root = path.join(__dirname, '../test/bed')
  9. , totalDirs = 6
  10. , totalFiles = 12
  11. , ext1Files = 4
  12. , ext2Files = 3
  13. , ext3Files = 2
  14. , rootDir2Files = 2
  15. , nameHasLength9Dirs = 2
  16. , depth1Files = 8
  17. , depth0Files = 3
  18. ;
  19. /*
  20. Structure of test bed:
  21. .
  22. ├── root_dir1
  23. │   ├── root_dir1_file1.ext1
  24. │   ├── root_dir1_file2.ext2
  25. │   ├── root_dir1_file3.ext3
  26. │   ├── root_dir1_subdir1
  27. │   │   └── root1_dir1_subdir1_file1.ext1
  28. │   └── root_dir1_subdir2
  29. │   └── .gitignore
  30. ├── root_dir2
  31. │   ├── root_dir2_file1.ext1
  32. │   ├── root_dir2_file2.ext2
  33. │   ├── root_dir2_subdir1
  34. │   │   └── .gitignore
  35. │   └── root_dir2_subdir2
  36. │   └── .gitignore
  37. ├── root_file1.ext1
  38. ├── root_file2.ext2
  39. └── root_file3.ext3
  40. 6 directories, 13 files
  41. */
  42. // console.log('\033[2J'); // clear console
  43. function opts (extend) {
  44. var o = { root: root };
  45. if (extend) {
  46. for (var prop in extend) {
  47. o[prop] = extend[prop];
  48. }
  49. }
  50. return o;
  51. }
  52. test('\nreading root without filter', function (t) {
  53. t.plan(2);
  54. readdirp(opts(), function (err, res) {
  55. t.equals(res.directories.length, totalDirs, 'all directories');
  56. t.equals(res.files.length, totalFiles, 'all files');
  57. t.end();
  58. })
  59. })
  60. test('\nreading root without filter using lstat', function (t) {
  61. t.plan(2);
  62. readdirp(opts({ lstat: true }), function (err, res) {
  63. t.equals(res.directories.length, totalDirs, 'all directories');
  64. t.equals(res.files.length, totalFiles, 'all files');
  65. t.end();
  66. })
  67. })
  68. test('\nreading root with symlinks using lstat', function (t) {
  69. t.plan(2);
  70. fs.symlinkSync(path.join(root, 'root_dir1'), path.join(root, 'dirlink'));
  71. fs.symlinkSync(path.join(root, 'root_file1.ext1'), path.join(root, 'link.ext1'));
  72. readdirp(opts({ lstat: true }), function (err, res) {
  73. t.equals(res.directories.length, totalDirs, 'all directories');
  74. t.equals(res.files.length, totalFiles + 2, 'all files + symlinks');
  75. fs.unlinkSync(path.join(root, 'dirlink'));
  76. fs.unlinkSync(path.join(root, 'link.ext1'));
  77. t.end();
  78. })
  79. })
  80. test('\nreading non-standard fds', function (t) {
  81. t.plan(2);
  82. var server = net.createServer().listen(path.join(root, 'test.sock'), function(){
  83. readdirp(opts({ entryType: 'all' }), function (err, res) {
  84. t.equals(res.files.length, totalFiles + 1, 'all files + socket');
  85. readdirp(opts({ entryType: 'both' }), function (err, res) {
  86. t.equals(res.files.length, totalFiles, 'all regular files only');
  87. server.close();
  88. t.end();
  89. })
  90. })
  91. });
  92. })
  93. test('\nreading root using glob filter', function (t) {
  94. // normal
  95. t.test('\n# "*.ext1"', function (t) {
  96. t.plan(1);
  97. readdirp(opts( { fileFilter: '*.ext1' } ), function (err, res) {
  98. t.equals(res.files.length, ext1Files, 'all ext1 files');
  99. t.end();
  100. })
  101. })
  102. t.test('\n# ["*.ext1", "*.ext3"]', function (t) {
  103. t.plan(1);
  104. readdirp(opts( { fileFilter: [ '*.ext1', '*.ext3' ] } ), function (err, res) {
  105. t.equals(res.files.length, ext1Files + ext3Files, 'all ext1 and ext3 files');
  106. t.end();
  107. })
  108. })
  109. t.test('\n# "root_dir1"', function (t) {
  110. t.plan(1);
  111. readdirp(opts( { directoryFilter: 'root_dir1' }), function (err, res) {
  112. t.equals(res.directories.length, 1, 'one directory');
  113. t.end();
  114. })
  115. })
  116. t.test('\n# ["root_dir1", "*dir1_subdir1"]', function (t) {
  117. t.plan(1);
  118. readdirp(opts( { directoryFilter: [ 'root_dir1', '*dir1_subdir1' ]}), function (err, res) {
  119. t.equals(res.directories.length, 2, 'two directories');
  120. t.end();
  121. })
  122. })
  123. t.test('\n# negated: "!*.ext1"', function (t) {
  124. t.plan(1);
  125. readdirp(opts( { fileFilter: '!*.ext1' } ), function (err, res) {
  126. t.equals(res.files.length, totalFiles - ext1Files, 'all but ext1 files');
  127. t.end();
  128. })
  129. })
  130. t.test('\n# negated: ["!*.ext1", "!*.ext3"]', function (t) {
  131. t.plan(1);
  132. readdirp(opts( { fileFilter: [ '!*.ext1', '!*.ext3' ] } ), function (err, res) {
  133. t.equals(res.files.length, totalFiles - ext1Files - ext3Files, 'all but ext1 and ext3 files');
  134. t.end();
  135. })
  136. })
  137. t.test('\n# mixed: ["*.ext1", "!*.ext3"]', function (t) {
  138. t.plan(1);
  139. readdirp(opts( { fileFilter: [ '*.ext1', '!*.ext3' ] } ), function (err, res) {
  140. t.similar(err[0].toString(), /Cannot mix negated with non negated glob filters/, 'returns meaningfull error');
  141. t.end();
  142. })
  143. })
  144. t.test('\n# leading and trailing spaces: [" *.ext1", "*.ext3 "]', function (t) {
  145. t.plan(1);
  146. readdirp(opts( { fileFilter: [ ' *.ext1', '*.ext3 ' ] } ), function (err, res) {
  147. t.equals(res.files.length, ext1Files + ext3Files, 'all ext1 and ext3 files');
  148. t.end();
  149. })
  150. })
  151. t.test('\n# leading and trailing spaces: [" !*.ext1", " !*.ext3 "]', function (t) {
  152. t.plan(1);
  153. readdirp(opts( { fileFilter: [ ' !*.ext1', ' !*.ext3' ] } ), function (err, res) {
  154. t.equals(res.files.length, totalFiles - ext1Files - ext3Files, 'all but ext1 and ext3 files');
  155. t.end();
  156. })
  157. })
  158. t.test('\n# ** glob pattern', function (t) {
  159. t.plan(1);
  160. readdirp(opts( { fileFilter: '**/*.ext1' } ), function (err, res) {
  161. t.equals(res.files.length, ext1Files, 'ignores ** in **/*.ext1 -> only *.ext1 files');
  162. t.end();
  163. })
  164. })
  165. })
  166. test('\n\nreading root using function filter', function (t) {
  167. t.test('\n# file filter -> "contains root_dir2"', function (t) {
  168. t.plan(1);
  169. readdirp(
  170. opts( { fileFilter: function (fi) { return fi.name.indexOf('root_dir2') >= 0; } })
  171. , function (err, res) {
  172. t.equals(res.files.length, rootDir2Files, 'all rootDir2Files');
  173. t.end();
  174. }
  175. )
  176. })
  177. t.test('\n# directory filter -> "name has length 9"', function (t) {
  178. t.plan(1);
  179. readdirp(
  180. opts( { directoryFilter: function (di) { return di.name.length === 9; } })
  181. , function (err, res) {
  182. t.equals(res.directories.length, nameHasLength9Dirs, 'all all dirs with name length 9');
  183. t.end();
  184. }
  185. )
  186. })
  187. })
  188. test('\nreading root specifying maximum depth', function (t) {
  189. t.test('\n# depth 1', function (t) {
  190. t.plan(1);
  191. readdirp(opts( { depth: 1 } ), function (err, res) {
  192. t.equals(res.files.length, depth1Files, 'does not return files at depth 2');
  193. })
  194. })
  195. })
  196. test('\nreading root with no recursion', function (t) {
  197. t.test('\n# depth 0', function (t) {
  198. t.plan(1);
  199. readdirp(opts( { depth: 0 } ), function (err, res) {
  200. t.equals(res.files.length, depth0Files, 'does not return files at depth 0');
  201. })
  202. })
  203. })
  204. test('\nprogress callbacks', function (t) {
  205. t.plan(2);
  206. var pluckName = function(fi) { return fi.name; }
  207. , processedFiles = [];
  208. readdirp(
  209. opts()
  210. , function(fi) {
  211. processedFiles.push(fi);
  212. }
  213. , function (err, res) {
  214. t.equals(processedFiles.length, res.files.length, 'calls back for each file processed');
  215. t.deepEquals(processedFiles.map(pluckName).sort(),res.files.map(pluckName).sort(), 'same file names');
  216. t.end();
  217. }
  218. )
  219. })
  220. test('resolving of name, full and relative paths', function (t) {
  221. var expected = {
  222. name : 'root_dir1_file1.ext1'
  223. , parentDirName : 'root_dir1'
  224. , path : 'root_dir1/root_dir1_file1.ext1'
  225. , fullPath : 'test/bed/root_dir1/root_dir1_file1.ext1'
  226. }
  227. , opts = [
  228. { root: './bed' , prefix: '' }
  229. , { root: './bed/' , prefix: '' }
  230. , { root: 'bed' , prefix: '' }
  231. , { root: 'bed/' , prefix: '' }
  232. , { root: '../test/bed/' , prefix: '' }
  233. , { root: '.' , prefix: 'bed' }
  234. ]
  235. t.plan(opts.length);
  236. opts.forEach(function (op) {
  237. op.fileFilter = 'root_dir1_file1.ext1';
  238. t.test('\n' + util.inspect(op), function (t) {
  239. t.plan(4);
  240. readdirp (op, function(err, res) {
  241. t.equals(res.files[0].name, expected.name, 'correct name');
  242. t.equals(res.files[0].path, path.join(op.prefix, expected.path), 'correct path');
  243. })
  244. fs.realpath(op.root, function(err, fullRoot) {
  245. readdirp (op, function(err, res) {
  246. t.equals(
  247. res.files[0].fullParentDir
  248. , path.join(fullRoot, op.prefix, expected.parentDirName)
  249. , 'correct parentDir'
  250. );
  251. t.equals(
  252. res.files[0].fullPath
  253. , path.join(fullRoot, op.prefix, expected.parentDirName, expected.name)
  254. , 'correct fullPath'
  255. );
  256. })
  257. })
  258. })
  259. })
  260. })