io_test.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. // Licensed to the Software Freedom Conservancy (SFC) under one
  2. // or more contributor license agreements. See the NOTICE file
  3. // distributed with this work for additional information
  4. // regarding copyright ownership. The SFC licenses this file
  5. // to you under the Apache License, Version 2.0 (the
  6. // "License"); you may not use this file except in compliance
  7. // with the License. You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing,
  12. // software distributed under the License is distributed on an
  13. // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. // KIND, either express or implied. See the License for the
  15. // specific language governing permissions and limitations
  16. // under the License.
  17. 'use strict';
  18. var assert = require('assert'),
  19. fs = require('fs'),
  20. path = require('path'),
  21. tmp = require('tmp');
  22. var io = require('../../io');
  23. describe('io', function() {
  24. describe('copy', function() {
  25. var tmpDir;
  26. before(function() {
  27. return io.tmpDir().then(function(d) {
  28. tmpDir = d;
  29. fs.writeFileSync(path.join(d, 'foo'), 'Hello, world');
  30. });
  31. });
  32. it('can copy one file to another', function() {
  33. return io.tmpFile().then(function(f) {
  34. return io.copy(path.join(tmpDir, 'foo'), f).then(function(p) {
  35. assert.equal(p, f);
  36. assert.equal('Hello, world', fs.readFileSync(p));
  37. });
  38. });
  39. });
  40. it('can copy symlink to destination', function() {
  41. if (process.platform === 'win32') {
  42. return; // No symlinks on windows.
  43. }
  44. fs.symlinkSync(
  45. path.join(tmpDir, 'foo'),
  46. path.join(tmpDir, 'symlinked-foo'));
  47. return io.tmpFile().then(function(f) {
  48. return io.copy(path.join(tmpDir, 'symlinked-foo'), f).then(function(p) {
  49. assert.equal(p, f);
  50. assert.equal('Hello, world', fs.readFileSync(p));
  51. });
  52. });
  53. });
  54. it('fails if given a directory as a source', function() {
  55. return io.tmpFile().then(function(f) {
  56. return io.copy(tmpDir, f);
  57. }).then(function() {
  58. throw Error('Should have failed with a type error');
  59. }, function() {
  60. // Do nothing; expected.
  61. });
  62. });
  63. });
  64. describe('copyDir', function() {
  65. it('copies recursively', function() {
  66. return io.tmpDir().then(function(dir) {
  67. fs.writeFileSync(path.join(dir, 'file1'), 'hello');
  68. fs.mkdirSync(path.join(dir, 'sub'));
  69. fs.mkdirSync(path.join(dir, 'sub/folder'));
  70. fs.writeFileSync(path.join(dir, 'sub/folder/file2'), 'goodbye');
  71. return io.tmpDir().then(function(dst) {
  72. return io.copyDir(dir, dst).then(function(ret) {
  73. assert.equal(dst, ret);
  74. assert.equal('hello',
  75. fs.readFileSync(path.join(dst, 'file1')));
  76. assert.equal('goodbye',
  77. fs.readFileSync(path.join(dst, 'sub/folder/file2')));
  78. });
  79. });
  80. });
  81. });
  82. it('creates destination dir if necessary', function() {
  83. return io.tmpDir().then(function(srcDir) {
  84. fs.writeFileSync(path.join(srcDir, 'foo'), 'hi');
  85. return io.tmpDir().then(function(dstDir) {
  86. return io.copyDir(srcDir, path.join(dstDir, 'sub'));
  87. });
  88. }).then(function(p) {
  89. assert.equal('sub', path.basename(p));
  90. assert.equal('hi', fs.readFileSync(path.join(p, 'foo')));
  91. });
  92. });
  93. it('supports regex exclusion filter', function() {
  94. return io.tmpDir().then(function(src) {
  95. fs.writeFileSync(path.join(src, 'foo'), 'a');
  96. fs.writeFileSync(path.join(src, 'bar'), 'b');
  97. fs.writeFileSync(path.join(src, 'baz'), 'c');
  98. fs.mkdirSync(path.join(src, 'sub'));
  99. fs.writeFileSync(path.join(src, 'sub/quux'), 'd');
  100. fs.writeFileSync(path.join(src, 'sub/quot'), 'e');
  101. return io.tmpDir().then(function(dst) {
  102. return io.copyDir(src, dst, /(bar|quux)/);
  103. });
  104. }).then(function(dir) {
  105. assert.equal('a', fs.readFileSync(path.join(dir, 'foo')));
  106. assert.equal('c', fs.readFileSync(path.join(dir, 'baz')));
  107. assert.equal('e', fs.readFileSync(path.join(dir, 'sub/quot')));
  108. assert.ok(!fs.existsSync(path.join(dir, 'bar')));
  109. assert.ok(!fs.existsSync(path.join(dir, 'sub/quux')));
  110. });
  111. });
  112. it('supports exclusion filter function', function() {
  113. return io.tmpDir().then(function(src) {
  114. fs.writeFileSync(path.join(src, 'foo'), 'a');
  115. fs.writeFileSync(path.join(src, 'bar'), 'b');
  116. fs.writeFileSync(path.join(src, 'baz'), 'c');
  117. fs.mkdirSync(path.join(src, 'sub'));
  118. fs.writeFileSync(path.join(src, 'sub/quux'), 'd');
  119. fs.writeFileSync(path.join(src, 'sub/quot'), 'e');
  120. return io.tmpDir().then(function(dst) {
  121. return io.copyDir(src, dst, function(f) {
  122. return f !== path.join(src, 'foo')
  123. && f !== path.join(src, 'sub/quot');
  124. });
  125. });
  126. }).then(function(dir) {
  127. assert.equal('b', fs.readFileSync(path.join(dir, 'bar')));
  128. assert.equal('c', fs.readFileSync(path.join(dir, 'baz')));
  129. assert.equal('d', fs.readFileSync(path.join(dir, 'sub/quux')));
  130. assert.ok(!fs.existsSync(path.join(dir, 'foo')));
  131. assert.ok(!fs.existsSync(path.join(dir, 'sub/quot')));
  132. });
  133. });
  134. });
  135. describe('exists', function() {
  136. var dir;
  137. before(function() {
  138. return io.tmpDir().then(function(d) {
  139. dir = d;
  140. });
  141. });
  142. it('returns a rejected promise if input value is invalid', function() {
  143. return io.exists(undefined).then(
  144. () => assert.fail('should have failed'),
  145. e => assert.ok(e instanceof TypeError));
  146. });
  147. it('works for directories', function() {
  148. return io.exists(dir).then(assert.ok);
  149. });
  150. it('works for files', function() {
  151. var file = path.join(dir, 'foo');
  152. fs.writeFileSync(file, '');
  153. return io.exists(file).then(assert.ok);
  154. });
  155. it('does not return a rejected promise if file does not exist', function() {
  156. return io.exists(path.join(dir, 'not-there')).then(function(exists) {
  157. assert.ok(!exists);
  158. });
  159. });
  160. });
  161. describe('unlink', function() {
  162. var dir;
  163. before(function() {
  164. return io.tmpDir().then(function(d) {
  165. dir = d;
  166. });
  167. });
  168. it('silently succeeds if the path does not exist', function() {
  169. return io.unlink(path.join(dir, 'not-there'));
  170. });
  171. it('deletes files', function() {
  172. var file = path.join(dir, 'foo');
  173. fs.writeFileSync(file, '');
  174. return io.exists(file).then(assert.ok).then(function() {
  175. return io.unlink(file);
  176. }).then(function() {
  177. return io.exists(file);
  178. }).then(function(exists) {
  179. return assert.ok(!exists);
  180. });
  181. });
  182. });
  183. describe('rmDir', function() {
  184. it('succeeds if the designated directory does not exist', function() {
  185. return io.tmpDir().then(function(d) {
  186. return io.rmDir(path.join(d, 'i/do/not/exist'));
  187. });
  188. });
  189. it('deletes recursively', function() {
  190. return io.tmpDir().then(function(dir) {
  191. fs.writeFileSync(path.join(dir, 'file1'), 'hello');
  192. fs.mkdirSync(path.join(dir, 'sub'));
  193. fs.mkdirSync(path.join(dir, 'sub/folder'));
  194. fs.writeFileSync(path.join(dir, 'sub/folder/file2'), 'goodbye');
  195. return io.rmDir(dir).then(function() {
  196. assert.ok(!fs.existsSync(dir));
  197. assert.ok(!fs.existsSync(path.join(dir, 'sub/folder/file2')));
  198. });
  199. });
  200. });
  201. });
  202. describe('findInPath', function() {
  203. const savedPathEnv = process.env['PATH'];
  204. afterEach(() => process.env['PATH'] = savedPathEnv);
  205. const cwd = process.cwd;
  206. afterEach(() => process.cwd = cwd);
  207. let dirs;
  208. beforeEach(() => {
  209. return Promise.all([io.tmpDir(), io.tmpDir(), io.tmpDir()]).then(arr => {
  210. dirs = arr;
  211. process.env['PATH'] = arr.join(path.delimiter);
  212. });
  213. });
  214. it('returns null if file cannot be found', () => {
  215. assert.strictEqual(io.findInPath('foo.txt'), null);
  216. });
  217. it('can find file on path', () => {
  218. let filePath = path.join(dirs[1], 'foo.txt');
  219. fs.writeFileSync(filePath, 'hi');
  220. assert.strictEqual(io.findInPath('foo.txt'), filePath);
  221. });
  222. it('returns null if file is in a subdir of a directory on the path', () => {
  223. let subDir = path.join(dirs[2], 'sub');
  224. fs.mkdirSync(subDir);
  225. let filePath = path.join(subDir, 'foo.txt');
  226. fs.writeFileSync(filePath, 'hi');
  227. assert.strictEqual(io.findInPath('foo.txt'), null);
  228. });
  229. it('does not match on directories', () => {
  230. fs.mkdirSync(path.join(dirs[2], 'sub'));
  231. assert.strictEqual(io.findInPath('sub'), null);
  232. });
  233. it('will look in cwd first if requested', () => {
  234. return io.tmpDir().then(fakeCwd => {
  235. process.cwd = () => fakeCwd;
  236. let theFile = path.join(fakeCwd, 'foo.txt');
  237. fs.writeFileSync(path.join(dirs[1], 'foo.txt'), 'hi');
  238. fs.writeFileSync(theFile, 'bye');
  239. assert.strictEqual(io.findInPath('foo.txt', true), theFile);
  240. });
  241. });
  242. });
  243. describe('read', function() {
  244. var tmpDir;
  245. before(function() {
  246. return io.tmpDir().then(function(d) {
  247. tmpDir = d;
  248. fs.writeFileSync(path.join(d, 'foo'), 'Hello, world');
  249. });
  250. });
  251. it('can read a file', function() {
  252. return io.read(path.join(tmpDir, 'foo')).then(buff => {
  253. assert.ok(buff instanceof Buffer);
  254. assert.equal('Hello, world', buff.toString());
  255. });
  256. });
  257. it('catches errors from invalid input', function() {
  258. return io.read({})
  259. .then(() => assert.fail('should have failed'),
  260. (e) => assert.ok(e instanceof TypeError));
  261. });
  262. it('rejects returned promise if file does not exist', function() {
  263. return io.read(path.join(tmpDir, 'not-there'))
  264. .then(() => assert.fail('should have failed'),
  265. (e) => assert.equal('ENOENT', e.code));
  266. });
  267. });
  268. describe('mkdirp', function() {
  269. it('recursively creates entire directory path', function() {
  270. return io.tmpDir().then(root => {
  271. let dst = path.join(root, 'foo/bar/baz');
  272. return io.mkdirp(dst).then(d => {
  273. assert.strictEqual(d, dst);
  274. return io.stat(d).then(stats => {
  275. assert.ok(stats.isDirectory());
  276. });
  277. });
  278. });
  279. });
  280. it('does nothing if the directory already exists', function() {
  281. return io.tmpDir()
  282. .then(dir => io.mkdirp(dir).then(d => assert.strictEqual(d, dir)));
  283. });
  284. });
  285. describe('walkDir', function() {
  286. it('walk directory', function() {
  287. return io.tmpDir().then(dir => {
  288. fs.writeFileSync(path.join(dir, 'file1'), 'hello');
  289. fs.mkdirSync(path.join(dir, 'sub'));
  290. fs.mkdirSync(path.join(dir, 'sub/folder'));
  291. fs.writeFileSync(path.join(dir, 'sub/folder/file2'), 'goodbye');
  292. return io.walkDir(dir).then(seen => {
  293. assert.deepStrictEqual(
  294. seen,
  295. [{path: 'file1', dir: false},
  296. {path: 'sub', dir: true},
  297. {path: 'sub/folder', dir: true},
  298. {path: 'sub/folder/file2', dir: false}]);
  299. });
  300. });
  301. });
  302. })
  303. });