UNPKG

mock-fs-require-fix

Version:

Fork of the tschaub/mock-fs project.

1,784 lines (1,468 loc) 87.7 kB
'use strict'; var Writable = require('stream').Writable; var assert = require('../helper').assert; var fs = require('fs'); var fork = require('child_process').fork; var mock = require('../../lib/index'); var os = require('os'); var path = require('path'); var testParentPerms = (fs.access && fs.accessSync && process.getuid && process.getgid); describe('The API', function() { describe('mock()', function() { it('configures the real fs module with a mock file system', function() { mock({ 'fake-file-for-testing-only': 'file content' }); assert.isTrue(fs.existsSync('fake-file-for-testing-only')); mock.restore(); }); it('creates process.cwd() and os.tmpdir() by default', function() { mock(); assert.isTrue(fs.statSync(process.cwd()).isDirectory()); var tmp; if (os.tmpdir) { tmp = os.tmpdir(); } else if (os.tmpDir) { tmp = os.tmpDir(); } if (tmp) { assert.isTrue(fs.statSync(tmp).isDirectory()); } mock.restore(); }); it('passes the createCwd option to the FileSystem constructor', function() { mock({}, {createCwd: false}); assert.isFalse(fs.existsSync(process.cwd())); mock.restore(); }); it('passes the createTmp option to the FileSystem constructor', function() { mock({}, {createTmp: false}); var tmp; if (os.tmpdir) { tmp = os.tmpdir(); } else if (os.tmpDir) { tmp = os.tmpDir(); } if (tmp) { assert.isFalse(fs.existsSync(tmp)); } mock.restore(); }); it('uses the real fs module in require() calls', function() { mock({foo: 'bar'}); var pkg = require('../../package.json'); assert.equal(pkg.name, 'mock-fs-require-fix'); mock.restore(); }); it('uses the mocked fs module after recent core require() calls', function(done) { var child = fork('../../fixtures/mock-fs-parent.js', { cwd: __dirname, silent: true }); var called = false; child.on('exit', function() { if (called) return; called = true; done(new Error('Sandbox was ignored')); }); child.stderr.on('data', function() { if (called) return; called = true; done(null); }); }); it('uses the mocked fs module after recent fs require() calls', function(done) { var child = fork('../../fixtures/mock-fs-parent-nested.js', { cwd: __dirname, silent: true }); var called = false; child.on('exit', function() { if (called) return; called = true; done(new Error('Sandbox was ignored')); }); child.stderr.on('data', function() { if (called) return; called = true; done(null); }); }); }); describe('mock.restore()', function() { it('restores bindings for the real file system', function() { mock({ 'fake-file-for-testing-only': 'file content' }); assert.isTrue(fs.existsSync('fake-file-for-testing-only')); mock.restore(); assert.isFalse(fs.existsSync('fake-file-for-testing-only')); }); }); describe('mock.file()', function() { afterEach(mock.restore); it('lets you create files with additional properties', function(done) { mock({ 'path/to/file.txt': mock.file({ content: 'file content', mtime: new Date(8675309), mode: parseInt('0644', 8) }) }); fs.stat('path/to/file.txt', function(err, stats) { if (err) { return done(err); } assert.isTrue(stats.isFile()); assert.isFalse(stats.isDirectory()); assert.equal(stats.mtime.getTime(), 8675309); assert.equal(stats.mode & parseInt('0777', 8), parseInt('0644', 8)); done(); }); }); }); describe('mock.directory()', function() { afterEach(mock.restore); it('lets you create directories with more properties', function(done) { mock({ 'path/to/dir': mock.directory({ mtime: new Date(8675309), mode: parseInt('0644', 8) }) }); fs.stat('path/to/dir', function(err, stats) { if (err) { return done(err); } assert.isFalse(stats.isFile()); assert.isTrue(stats.isDirectory()); assert.equal(stats.mtime.getTime(), 8675309); assert.equal(stats.mode & parseInt('0777', 8), parseInt('0644', 8)); done(); }); }); it('works with a trailing slash', function() { mock({ 'path/to/dir/': mock.directory({ mtime: new Date(8675309), mode: parseInt('0644', 8) }) }); assert.isTrue(fs.statSync('path/to/dir').isDirectory()); assert.isTrue(fs.statSync('path/to/dir/').isDirectory()); }); it('works without a trailing slash', function() { mock({ 'path/to/dir': mock.directory({ mtime: new Date(8675309), mode: parseInt('0644', 8) }) }); assert.isTrue(fs.statSync('path/to/dir').isDirectory()); assert.isTrue(fs.statSync('path/to/dir/').isDirectory()); }); }); describe('mock.symlink()', function() { afterEach(mock.restore); it('lets you create symbolic links', function() { mock({ 'path/to/file': 'content', 'path/to/link': mock.symlink({path: './file'}) }); var stats = fs.statSync('path/to/link'); assert.isTrue(stats.isFile()); assert.equal(String(fs.readFileSync('path/to/link')), 'content'); }); }); describe('mock.fs()', function() { it('generates a mock fs module with a mock file system', function(done) { var mockFs = mock.fs({ 'path/to/file.txt': 'file content' }); mockFs.exists('path/to/file.txt', function(exists) { assert.isTrue(exists); done(); }); }); it('passes options to the FileSystem constructor', function() { var mockFs = mock.fs({ '/path/to/file.txt': 'file content' }, { createCwd: false, createTmp: false }); assert.isTrue(mockFs.existsSync('/path/to/file.txt')); assert.deepEqual(mockFs.readdirSync('/'), ['path']); }); it('accepts an arbitrary nesting of files and directories', function() { var mockFs = mock.fs({ 'dir-one': { 'dir-two': { 'some-file.txt': 'file content here' } }, 'empty-dir': {} }); assert.isTrue(mockFs.existsSync('dir-one/dir-two/some-file.txt')); assert.isTrue(mockFs.statSync('dir-one/dir-two/some-file.txt').isFile()); assert.isTrue(mockFs.statSync('dir-one/dir-two').isDirectory()); assert.isTrue(mockFs.statSync('empty-dir').isDirectory()); }); }); }); describe('Mocking the file system', function() { if (fs.access && fs.accessSync && process.getuid && process.getgid) { // TODO: drop condition when dropping Node < 0.12 support // TODO: figure out how fs.access() works on Windows (without gid/uid) describe('fs.access(path[, mode], callback)', function() { beforeEach(function() { mock({ 'path/to/accessible/file': 'can access', 'path/to/000': mock.file({ mode: parseInt('0000', 8), content: 'no permissions' }), 'path/to/111': mock.file({ mode: parseInt('0111', 8), content: 'execute only' }), 'path/to/write/only': mock.file({ mode: parseInt('0222', 8), content: 'write only' }), 'path/to/333': mock.file({ mode: parseInt('0333', 8), content: 'write and execute' }), 'path/to/444': mock.file({ mode: parseInt('0444', 8), content: 'read only' }), 'path/to/555': mock.file({ mode: parseInt('0555', 8), content: 'read and execute' }), 'path/to/666': mock.file({ mode: parseInt('0666', 8), content: 'read and write' }), 'path/to/777': mock.file({ mode: parseInt('0777', 8), content: 'read, write, and execute' }), 'unreadable': mock.directory({mode: parseInt('0000', 8), items: { 'readable-child': mock.file({ mode: parseInt('0777', 8), content: 'read, write, and execute' }) }}) }); }); afterEach(mock.restore); it('works for an accessible file', function(done) { fs.access('path/to/accessible/file', done); }); it('works 000 (and no mode arg)', function(done) { fs.access('path/to/000', done); }); it('works F_OK and 000', function(done) { fs.access('path/to/000', fs.F_OK, done); }); it('generates EACCES for R_OK and 000', function(done) { fs.access('path/to/000', fs.R_OK, function(err) { assert.instanceOf(err, Error); assert.equal(err.code, 'EACCES'); done(); }); }); it('generates EACCES for W_OK and 000', function(done) { fs.access('path/to/000', fs.W_OK, function(err) { assert.instanceOf(err, Error); assert.equal(err.code, 'EACCES'); done(); }); }); it('generates EACCES for X_OK and 000', function(done) { fs.access('path/to/000', fs.X_OK, function(err) { assert.instanceOf(err, Error); assert.equal(err.code, 'EACCES'); done(); }); }); it('works 111 (and no mode arg)', function(done) { fs.access('path/to/111', done); }); it('works F_OK and 111', function(done) { fs.access('path/to/111', fs.F_OK, done); }); it('works X_OK and 111', function(done) { fs.access('path/to/111', fs.X_OK, done); }); it('generates EACCES for R_OK and 111', function(done) { fs.access('path/to/111', fs.R_OK, function(err) { assert.instanceOf(err, Error); assert.equal(err.code, 'EACCES'); done(); }); }); it('generates EACCES for W_OK and 111', function(done) { fs.access('path/to/111', fs.W_OK, function(err) { assert.instanceOf(err, Error); assert.equal(err.code, 'EACCES'); done(); }); }); it('works for 222 (and no mode arg)', function(done) { fs.access('path/to/write/only', done); }); it('works F_OK and 222', function(done) { fs.access('path/to/write/only', fs.F_OK, done); }); it('works W_OK and 222', function(done) { fs.access('path/to/write/only', fs.W_OK, done); }); it('generates EACCES for R_OK and 222', function(done) { fs.access('path/to/write/only', fs.R_OK, function(err) { assert.instanceOf(err, Error); assert.equal(err.code, 'EACCES'); done(); }); }); it('generates EACCES for X_OK and 222', function(done) { fs.access('path/to/write/only', fs.X_OK, function(err) { assert.instanceOf(err, Error); assert.equal(err.code, 'EACCES'); done(); }); }); it('works for 333 (and no mode arg)', function(done) { fs.access('path/to/333', done); }); it('works F_OK and 333', function(done) { fs.access('path/to/333', fs.F_OK, done); }); it('works W_OK and 333', function(done) { fs.access('path/to/333', fs.W_OK, done); }); it('works X_OK and 333', function(done) { fs.access('path/to/333', fs.X_OK, done); }); it('works X_OK | W_OK and 333', function(done) { fs.access('path/to/333', fs.X_OK | fs.W_OK, done); }); it('generates EACCES for R_OK and 333', function(done) { fs.access('path/to/333', fs.R_OK, function(err) { assert.instanceOf(err, Error); assert.equal(err.code, 'EACCES'); done(); }); }); it('works for 444 (and no mode arg)', function(done) { fs.access('path/to/444', done); }); it('works F_OK and 444', function(done) { fs.access('path/to/444', fs.F_OK, done); }); it('works R_OK and 444', function(done) { fs.access('path/to/444', fs.R_OK, done); }); it('generates EACCES for W_OK and 444', function(done) { fs.access('path/to/444', fs.W_OK, function(err) { assert.instanceOf(err, Error); assert.equal(err.code, 'EACCES'); done(); }); }); it('generates EACCES for X_OK and 444', function(done) { fs.access('path/to/444', fs.X_OK, function(err) { assert.instanceOf(err, Error); assert.equal(err.code, 'EACCES'); done(); }); }); it('works for 555 (and no mode arg)', function(done) { fs.access('path/to/555', done); }); it('works F_OK and 555', function(done) { fs.access('path/to/555', fs.F_OK, done); }); it('works R_OK and 555', function(done) { fs.access('path/to/555', fs.R_OK, done); }); it('works X_OK and 555', function(done) { fs.access('path/to/555', fs.X_OK, done); }); it('works R_OK | X_OK and 555', function(done) { fs.access('path/to/555', fs.R_OK | fs.X_OK, done); }); it('generates EACCES for W_OK and 555', function(done) { fs.access('path/to/555', fs.W_OK, function(err) { assert.instanceOf(err, Error); assert.equal(err.code, 'EACCES'); done(); }); }); it('works for 666 (and no mode arg)', function(done) { fs.access('path/to/666', done); }); it('works F_OK and 666', function(done) { fs.access('path/to/666', fs.F_OK, done); }); it('works R_OK and 666', function(done) { fs.access('path/to/666', fs.R_OK, done); }); it('works W_OK and 666', function(done) { fs.access('path/to/666', fs.W_OK, done); }); it('works R_OK | W_OK and 666', function(done) { fs.access('path/to/666', fs.R_OK | fs.W_OK, done); }); it('generates EACCES for X_OK and 666', function(done) { fs.access('path/to/666', fs.X_OK, function(err) { assert.instanceOf(err, Error); assert.equal(err.code, 'EACCES'); done(); }); }); it('works for 777 (and no mode arg)', function(done) { fs.access('path/to/777', done); }); it('works F_OK and 777', function(done) { fs.access('path/to/777', fs.F_OK, done); }); it('works R_OK and 777', function(done) { fs.access('path/to/777', fs.R_OK, done); }); it('works W_OK and 777', function(done) { fs.access('path/to/777', fs.W_OK, done); }); it('works X_OK and 777', function(done) { fs.access('path/to/777', fs.X_OK, done); }); it('works X_OK | W_OK and 777', function(done) { fs.access('path/to/777', fs.X_OK | fs.W_OK, done); }); it('works X_OK | R_OK and 777', function(done) { fs.access('path/to/777', fs.X_OK | fs.R_OK, done); }); it('works R_OK | W_OK and 777', function(done) { fs.access('path/to/777', fs.R_OK | fs.W_OK, done); }); it('works R_OK | W_OK | X_OK and 777', function(done) { fs.access('path/to/777', fs.R_OK | fs.W_OK | fs.X_OK, done); }); it('generates EACCESS for F_OK and an unreadable parent', function(done) { fs.access('unreadable/readable-child', function(err) { assert.instanceOf(err, Error); assert.equal(err.code, 'EACCES'); done(); }); }); }); describe('fs.accessSync(path[, mode])', function() { beforeEach(function() { mock({ 'path/to/777': mock.file({ mode: parseInt('0777', 8), content: 'all access' }), 'path/to/000': mock.file({ mode: parseInt('0000', 8), content: 'no permissions' }) }); }); afterEach(mock.restore); it('works for an accessible file', function() { fs.accessSync('path/to/777'); fs.accessSync('path/to/777', fs.F_OK); fs.accessSync('path/to/777', fs.X_OK); fs.accessSync('path/to/777', fs.W_OK); fs.accessSync('path/to/777', fs.X_OK | fs.W_OK); fs.accessSync('path/to/777', fs.R_OK); fs.accessSync('path/to/777', fs.X_OK | fs.R_OK); fs.accessSync('path/to/777', fs.W_OK | fs.R_OK); fs.accessSync('path/to/777', fs.X_OK | fs.W_OK | fs.R_OK); }); it('throws EACCESS for all but F_OK for 000', function() { fs.accessSync('path/to/000'); assert.throws(function() { fs.accessSync('path/to/000', fs.X_OK); }); assert.throws(function() { fs.accessSync('path/to/000', fs.W_OK); }); assert.throws(function() { fs.accessSync('path/to/000', fs.X_OK | fs.W_OK); }); assert.throws(function() { fs.accessSync('path/to/000', fs.R_OK); }); assert.throws(function() { fs.accessSync('path/to/000', fs.X_OK | fs.R_OK); }); assert.throws(function() { fs.accessSync('path/to/000', fs.W_OK | fs.R_OK); }); assert.throws(function() { fs.accessSync('path/to/000', fs.X_OK | fs.W_OK | fs.R_OK); }); }); }); } describe('fs.rename(oldPath, newPath, callback)', function() { beforeEach(function() { mock({ 'path/to/a.bin': new Buffer([1, 2, 3]), 'empty': {}, 'nested': { 'dir': mock.directory({ mtime: new Date(1), items: {'file.txt': ''} }) } }); }); afterEach(mock.restore); it('allows files to be renamed', function(done) { fs.rename('path/to/a.bin', 'path/to/b.bin', function(err) { assert.isTrue(!err); assert.isFalse(fs.existsSync('path/to/a.bin')); assert.isTrue(fs.existsSync('path/to/b.bin')); done(); }); }); it('updates mtime of parent directory', function(done) { var oldTime = fs.statSync('nested/dir').mtime; fs.rename('nested/dir/file.txt', 'nested/dir/renamed.txt', function(err) { assert.isTrue(!err); assert.isFalse(fs.existsSync('nested/dir/file.txt')); assert.isTrue(fs.existsSync('nested/dir/renamed.txt')); var newTime = fs.statSync('nested/dir').mtime; assert.isTrue(newTime > oldTime); done(); }); }); it('calls callback with error if old path does not exist', function(done) { fs.rename('bogus', 'empty', function(err) { assert.instanceOf(err, Error); done(); }); }); it('overwrites existing files', function(done) { fs.rename('path/to/a.bin', 'nested/dir/file.txt', function(err) { assert.isTrue(!err); assert.isFalse(fs.existsSync('path/to/a.bin')); assert.isTrue(fs.existsSync('nested/dir/file.txt')); done(); }); }); it('allows directories to be renamed', function(done) { fs.rename('path/to', 'path/foo', function(err) { assert.isTrue(!err); assert.isFalse(fs.existsSync('path/to')); assert.isTrue(fs.existsSync('path/foo')); assert.deepEqual(fs.readdirSync('path/foo'), ['a.bin']); done(); }); }); it('calls callback with error if new directory not empty', function(done) { fs.rename('path', 'nested', function(err) { assert.instanceOf(err, Error); done(); }); }); }); describe('fs.renameSync(oldPath, newPath)', function() { beforeEach(function() { mock({ 'path/to/a.bin': new Buffer([1, 2, 3]), 'empty': {}, 'nested': { 'dir': { 'file.txt': '' } }, 'link': mock.symlink({path: './path/to/a.bin'}) }); }); afterEach(mock.restore); it('allows files to be renamed', function() { fs.renameSync('path/to/a.bin', 'path/to/b.bin'); assert.isFalse(fs.existsSync('path/to/a.bin')); assert.isTrue(fs.existsSync('path/to/b.bin')); }); it('overwrites existing files', function() { fs.renameSync('path/to/a.bin', 'nested/dir/file.txt'); assert.isFalse(fs.existsSync('path/to/a.bin')); assert.isTrue(fs.existsSync('nested/dir/file.txt')); }); it('allows directories to be renamed', function() { fs.renameSync('path/to', 'path/foo'); assert.isFalse(fs.existsSync('path/to')); assert.isTrue(fs.existsSync('path/foo')); assert.deepEqual(fs.readdirSync('path/foo'), ['a.bin']); }); it('replaces existing directories (if empty)', function() { fs.renameSync('path/to', 'empty'); assert.isFalse(fs.existsSync('path/to')); assert.isTrue(fs.existsSync('empty')); assert.deepEqual(fs.readdirSync('empty'), ['a.bin']); }); it('renames symbolic links', function() { fs.renameSync('link', 'renamed'); assert.isTrue(fs.existsSync('renamed')); assert.isFalse(fs.existsSync('link')); assert.isTrue(fs.existsSync('path/to/a.bin')); }); it('throws if old path does not exist', function() { assert.throws(function() { fs.renameSync('bogus', 'empty'); }); }); it('throws if new path basename is not directory', function() { assert.throws(function() { fs.renameSync('path/to/a.bin', 'bogus/a.bin'); }); }); it('throws if new dir is not empty dir', function() { assert.throws(function() { fs.renameSync('path/to', 'nested'); }); }); }); describe('fs.stat(path, callback)', function() { beforeEach(function() { mock({ '/path/to/file.txt': mock.file({ ctime: new Date(1), mtime: new Date(2), atime: new Date(3), uid: 42, gid: 43 }), '/dir/symlink': mock.symlink({path: '/path/to/file.txt'}), '/empty': {} }); }); afterEach(mock.restore); it('creates an instance of fs.Stats', function(done) { fs.stat('/path/to/file.txt', function(err, stats) { if (err) { return done(err); } assert.instanceOf(stats, fs.Stats); done(); }); }); it('identifies files', function(done) { fs.stat('/path/to/file.txt', function(err, stats) { if (err) { return done(err); } assert.isTrue(stats.isFile()); assert.isFalse(stats.isDirectory()); done(); }); }); it('identifies directories', function(done) { fs.stat('/empty', function(err, stats) { if (err) { return done(err); } assert.isTrue(stats.isDirectory()); assert.isFalse(stats.isFile()); done(); }); }); it('provides file stats', function(done) { fs.stat('/path/to/file.txt', function(err, stats) { if (err) { return done(err); } assert.equal(stats.ctime.getTime(), 1); assert.equal(stats.mtime.getTime(), 2); assert.equal(stats.atime.getTime(), 3); assert.equal(stats.uid, 42); assert.equal(stats.gid, 43); assert.equal(stats.nlink, 1); assert.isNumber(stats.blocks); assert.isNumber(stats.blksize); assert.isNumber(stats.rdev); done(); }); }); it('provides directory stats', function(done) { fs.stat('/path', function(err, stats) { if (err) { return done(err); } assert.instanceOf(stats.ctime, Date); assert.instanceOf(stats.mtime, Date); assert.instanceOf(stats.atime, Date); if (process.getuid) { assert.isNumber(stats.uid); } else { assert.isUndefined(stats.uid); } if (process.getgid) { assert.isNumber(stats.gid); } else { assert.isUndefined(stats.gid); } assert.equal(stats.nlink, 3); assert.isNumber(stats.blocks); assert.isNumber(stats.blksize); assert.isNumber(stats.rdev); done(); }); }); }); describe('fs.fstat(fd, callback)', function() { beforeEach(function() { mock({ 'path/to/file.txt': 'file content', 'empty': {} }); }); afterEach(mock.restore); it('accepts a file descriptor for a file (r)', function(done) { var fd = fs.openSync('path/to/file.txt', 'r'); fs.fstat(fd, function(err, stats) { if (err) { return done(err); } assert.isTrue(stats.isFile()); assert.equal(stats.size, 12); done(); }); }); it('accepts a file descriptor for a directory (r)', function(done) { var fd = fs.openSync('path/to', 'r'); fs.fstat(fd, function(err, stats) { if (err) { return done(err); } assert.isTrue(stats.isDirectory()); assert.isTrue(stats.size > 0); done(); }); }); it('fails for bad file descriptor', function(done) { var fd = fs.openSync('path/to/file.txt', 'r'); fs.closeSync(fd); fs.fstat(fd, function(err, stats) { assert.instanceOf(err, Error); done(); }); }); }); describe('fs.fstatSync(fd)', function() { beforeEach(function() { mock({ 'path/to/file.txt': 'file content', 'empty': {} }); }); afterEach(mock.restore); it('accepts a file descriptor for a file (r)', function() { var fd = fs.openSync('path/to/file.txt', 'r'); var stats = fs.fstatSync(fd); assert.isTrue(stats.isFile()); assert.equal(stats.size, 12); }); it('accepts a file descriptor for a directory (r)', function() { var fd = fs.openSync('path/to', 'r'); var stats = fs.fstatSync(fd); assert.isTrue(stats.isDirectory()); assert.isTrue(stats.size > 0); }); it('fails for bad file descriptor', function() { var fd = fs.openSync('path/to/file.txt', 'r'); fs.closeSync(fd); assert.throws(function() { fs.fstatSync(fd); }); }); }); describe('fs.exists(path, callback)', function() { beforeEach(function() { mock({ 'path/to/a.bin': new Buffer([1, 2, 3]), 'empty': {}, 'nested': { 'dir': { 'file.txt': '' } } }); }); afterEach(mock.restore); it('calls with true if file exists', function(done) { fs.exists(path.join('path', 'to', 'a.bin'), function(exists) { assert.isTrue(exists); done(); }); }); it('calls with true if directory exists', function(done) { fs.exists('path', function(exists) { assert.isTrue(exists); done(); }); }); it('calls with true if empty directory exists', function(done) { fs.exists('empty', function(exists) { assert.isTrue(exists); done(); }); }); it('calls with true if nested directory exists', function(done) { fs.exists(path.join('nested', 'dir'), function(exists) { assert.isTrue(exists); done(); }); }); it('calls with true if file exists', function(done) { fs.exists(path.join('path', 'to', 'a.bin'), function(exists) { assert.isTrue(exists); done(); }); }); it('calls with true if empty file exists', function(done) { fs.exists(path.join('nested', 'dir', 'file.txt'), function(exists) { assert.isTrue(exists); done(); }); }); it('calls with false for bogus path', function(done) { fs.exists(path.join('bogus', 'path'), function(exists) { assert.isFalse(exists); done(); }); }); it('calls with false for bogus path (II)', function(done) { fs.exists(path.join('nested', 'dir', 'none'), function(exists) { assert.isFalse(exists); done(); }); }); }); describe('fs.existsSync(path)', function() { beforeEach(function() { mock({ 'path/to/a.bin': new Buffer([1, 2, 3]), 'empty': {}, 'nested': { 'dir': { 'file.txt': '' } } }); }); afterEach(mock.restore); it('returns true if file exists', function() { assert.isTrue(fs.existsSync(path.join('path', 'to', 'a.bin'))); }); it('returns true if directory exists', function() { assert.isTrue(fs.existsSync('path')); }); it('returns true if empty directory exists', function() { assert.isTrue(fs.existsSync('empty')); }); it('returns true if nested directory exists', function() { assert.isTrue(fs.existsSync(path.join('nested', 'dir'))); }); it('returns true if file exists', function() { assert.isTrue(fs.existsSync(path.join('path', 'to', 'a.bin'))); }); it('returns true if empty file exists', function() { assert.isTrue(fs.existsSync(path.join('nested', 'dir', 'file.txt'))); }); it('returns false for bogus path', function() { assert.isFalse(fs.existsSync(path.join('bogus', 'path'))); }); it('returns false for bogus path (II)', function() { assert.isFalse(fs.existsSync(path.join('nested', 'dir', 'none'))); }); }); describe('fs.readdirSync(path)', function() { beforeEach(function() { mock({ 'path/to/file.txt': 'file content', 'nested': { 'sub': { 'dir': { 'one.txt': 'one content', 'two.txt': 'two content', 'empty': {} } } } }); }); afterEach(mock.restore); it('lists directory contents', function() { var items = fs.readdirSync(path.join('path', 'to')); assert.isArray(items); assert.deepEqual(items, ['file.txt']); }); it('lists nested directory contents', function() { var items = fs.readdirSync(path.join('nested', 'sub', 'dir')); assert.isArray(items); assert.deepEqual(items, ['empty', 'one.txt', 'two.txt']); }); it('throws for bogus path', function() { assert.throws(function() { fs.readdirSync('bogus'); }); }); }); describe('fs.readdir(path, callback)', function() { beforeEach(function() { mock({ 'path/to/file.txt': 'file content', 'nested': { 'sub': { 'dir': { 'one.txt': 'one content', 'two.txt': 'two content', 'empty': {} } } } }); }); afterEach(mock.restore); it('lists directory contents', function(done) { fs.readdir(path.join('path', 'to'), function(err, items) { assert.isNull(err); assert.isArray(items); assert.deepEqual(items, ['file.txt']); done(); }); }); it('lists nested directory contents', function(done) { fs.readdir(path.join('nested', 'sub', 'dir'), function(err, items) { assert.isNull(err); assert.isArray(items); assert.deepEqual(items, ['empty', 'one.txt', 'two.txt']); done(); }); }); it('calls with an error for bogus path', function(done) { fs.readdir('bogus', function(err, items) { assert.instanceOf(err, Error); assert.isUndefined(items); done(); }); }); }); describe('fs.readdirSync(path)', function() { beforeEach(function() { mock({ 'path/to/file.txt': 'file content', 'nested': { 'sub': { 'dir': { 'one.txt': 'one content', 'two.txt': 'two content', 'empty': {} } } } }); }); afterEach(mock.restore); it('lists directory contents', function() { var items = fs.readdirSync(path.join('path', 'to')); assert.isArray(items); assert.deepEqual(items, ['file.txt']); }); it('lists nested directory contents', function() { var items = fs.readdirSync(path.join('nested', 'sub', 'dir')); assert.isArray(items); assert.deepEqual(items, ['empty', 'one.txt', 'two.txt']); }); it('throws for bogus path', function() { assert.throws(function() { fs.readdirSync('bogus'); }); }); }); describe('fs.open(path, flags, [mode], callback)', function() { beforeEach(function() { mock({ 'path/to/file.txt': 'file content', 'nested': { 'sub': { 'dir': { 'one.txt': 'one content', 'two.txt': 'two content', 'empty': {} } } } }); }); afterEach(mock.restore); it('opens an existing file for reading (r)', function(done) { fs.open('nested/sub/dir/one.txt', 'r', function(err, fd) { if (err) { return done(err); } assert.isNumber(fd); done(); }); }); it('fails if file does not exist (r)', function(done) { fs.open('bogus.txt', 'r', function(err, fd) { assert.instanceOf(err, Error); done(); }); }); it('creates a new file for writing (w)', function(done) { fs.open('path/to/new.txt', 'w', parseInt('0666', 8), function(err, fd) { if (err) { return done(err); } assert.isNumber(fd); assert.isTrue(fs.existsSync('path/to/new.txt')); done(); }); }); it('opens an existing file for writing (w)', function(done) { fs.open('path/to/one.txt', 'w', parseInt('0666', 8), function(err, fd) { if (err) { return done(err); } assert.isNumber(fd); done(); }); }); it('fails if file exists (wx)', function(done) { fs.open('path/to/one.txt', 'wx', parseInt('0666', 8), function(err, fd) { if (err) { return done(err); } assert.isNumber(fd); done(); }); }); }); describe('fs.openSync(path, flags, [mode])', function() { beforeEach(function() { mock({ 'path/to/file.txt': 'file content', 'nested': { 'sub': { 'dir': { 'one.txt': 'one content', 'two.txt': 'two content', 'empty': {} } } } }); }); afterEach(mock.restore); it('opens an existing file for reading (r)', function() { var fd = fs.openSync('path/to/file.txt', 'r'); assert.isNumber(fd); }); it('fails if file does not exist (r)', function() { assert.throws(function() { fs.openSync('bogus.txt', 'r'); }); }); it('creates a new file for writing (w)', function() { var fd = fs.openSync('nested/sub/new.txt', 'w', parseInt('0666', 8)); assert.isNumber(fd); assert.isTrue(fs.existsSync('nested/sub/new.txt')); }); it('opens an existing file for writing (w)', function() { var fd = fs.openSync('path/to/one.txt', 'w', parseInt('0666', 8)); assert.isNumber(fd); }); it('fails if file exists (wx)', function() { assert.throws(function() { fs.openSync('path/to/file.txt', 'wx', parseInt('0666', 8)); }); }); }); describe('fs.close(fd, callback)', function() { beforeEach(function() { mock({'dir': {}}); }); afterEach(mock.restore); it('closes a file descriptor', function(done) { var fd = fs.openSync('dir/file.txt', 'w'); fs.close(fd, function(err) { done(err); }); }); it('fails for closed file descriptors', function(done) { var fd = fs.openSync('dir/file.txt', 'w'); fs.close(fd, function(err) { if (err) { return done(err); } fs.close(fd, function(err2) { assert.instanceOf(err2, Error); done(); }); }); }); }); describe('fs.closeSync(fd)', function() { beforeEach(function() { mock({'dir': {}}); }); afterEach(mock.restore); it('closes a file descriptor', function() { var fd = fs.openSync('dir/file.txt', 'w'); fs.closeSync(fd); }); it('fails for closed file descriptors', function() { var fd = fs.openSync('dir/file.txt', 'w'); fs.closeSync(fd); assert.throws(function() { fs.closeSync(fd); }); }); }); describe('fs.read(fd, buffer, offset, length, position, callback)', function() { beforeEach(function() { mock({ 'path/to/file.txt': 'file content' }); }); afterEach(mock.restore); it('allows file contents to be read', function(done) { fs.open('path/to/file.txt', 'r', function(err, fd) { if (err) { return done(err); } var buffer = new Buffer(12); fs.read(fd, buffer, 0, 12, 0, function(err2, bytesRead, buf) { if (err2) { return done(err2); } assert.equal(bytesRead, 12); assert.equal(buf, buffer); assert.equal(String(buffer), 'file content'); done(); }); }); }); it('allows file contents to be read w/ offset', function(done) { fs.open('path/to/file.txt', 'r', function(err, fd) { if (err) { return done(err); } var buffer = new Buffer(12); fs.read(fd, buffer, 5, 12, 0, function(err2, bytesRead, buf) { if (err2) { return done(err2); } assert.equal(bytesRead, 7); assert.equal(buf, buffer); assert.equal(String(buffer.slice(5)), 'file co'); done(); }); }); }); it('allows file contents to be read w/ length', function(done) { fs.open('path/to/file.txt', 'r', function(err, fd) { if (err) { return done(err); } var buffer = new Buffer(12); fs.read(fd, buffer, 0, 4, 0, function(err2, bytesRead, buf) { if (err2) { return done(err2); } assert.equal(bytesRead, 4); assert.equal(buf, buffer); assert.equal(String(buffer.slice(0, 4)), 'file'); done(); }); }); }); it('allows file contents to be read w/ offset & length', function(done) { fs.open('path/to/file.txt', 'r', function(err, fd) { if (err) { return done(err); } var buffer = new Buffer(12); fs.read(fd, buffer, 2, 4, 0, function(err2, bytesRead, buf) { if (err2) { return done(err2); } assert.equal(bytesRead, 4); assert.equal(buf, buffer); assert.equal(String(buffer.slice(2, 6)), 'file'); done(); }); }); }); it('allows file contents to be read w/ position', function(done) { fs.open('path/to/file.txt', 'r', function(err, fd) { if (err) { return done(err); } var buffer = new Buffer(7); fs.read(fd, buffer, 0, 7, 5, function(err2, bytesRead, buf) { if (err2) { return done(err2); } assert.equal(bytesRead, 7); assert.equal(buf, buffer); assert.equal(String(buffer), 'content'); done(); }); }); }); it('allows read w/ offset, length, & position', function(done) { fs.open('path/to/file.txt', 'r', function(err, fd) { if (err) { return done(err); } var buffer = new Buffer(12); fs.read(fd, buffer, 2, 7, 5, function(err2, bytesRead, buf) { if (err2) { return done(err2); } assert.equal(bytesRead, 7); assert.equal(buf, buffer); assert.equal(String(buffer.slice(2, 9)), 'content'); done(); }); }); }); it('fails for closed file descriptor', function(done) { var fd = fs.openSync('path/to/file.txt', 'r'); fs.closeSync(fd); fs.read(fd, new Buffer(12), 0, 12, 0, function(err, bytesRead, buf) { assert.instanceOf(err, Error); assert.equal(0, bytesRead); done(); }); }); it('fails if not open for reading', function(done) { var fd = fs.openSync('path/to/file.txt', 'w'); fs.read(fd, new Buffer(12), 0, 12, 0, function(err, bytesRead, buf) { assert.instanceOf(err, Error); assert.equal(0, bytesRead); done(); }); }); }); describe('fs.readSync(fd, buffer, offset, length, position)', function() { beforeEach(function() { mock({ 'path/to/file.txt': 'file content' }); }); afterEach(mock.restore); it('allows a file to be read synchronously', function() { var fd = fs.openSync('path/to/file.txt', 'r'); var buffer = new Buffer(12); var read = fs.readSync(fd, buffer, 0, 12, 0); assert.equal(read, 12); assert.equal(String(buffer), 'file content'); }); it('allows a file to be read in two parts', function() { var fd = fs.openSync('path/to/file.txt', 'r'); var first = new Buffer(4); fs.readSync(fd, first, 0, 4, 0); assert.equal(String(first), 'file'); var second = new Buffer(7); fs.readSync(fd, second, 0, 7, 5); assert.equal(String(second), 'content'); }); it('treats null position as current position', function() { var fd = fs.openSync('path/to/file.txt', 'r'); var first = new Buffer(4); fs.readSync(fd, first, 0, 4, null); assert.equal(String(first), 'file'); // consume the space assert.equal(fs.readSync(fd, new Buffer(1), 0, 1, null), 1); var second = new Buffer(7); fs.readSync(fd, second, 0, 7, null); assert.equal(String(second), 'content'); }); }); describe('fs.readFile(filename, [options], callback)', function() { // this is provided by fs.open, fs.fstat, and fs.read // so more heavily tested elsewhere beforeEach(function() { mock({ 'path/to/file.txt': 'file content' }); }); afterEach(mock.restore); it('allows a file to be read asynchronously', function(done) { fs.readFile('path/to/file.txt', function(err, data) { if (err) { return done(err); } assert.isTrue(Buffer.isBuffer(data)); assert.equal(String(data), 'file content'); done(); }); }); it('fails for directory', function(done) { fs.readFile('path/to', function(err, data) { assert.instanceOf(err, Error); done(); }); }); it('fails for bad path', function(done) { fs.readFile('path/to/bogus', function(err, data) { assert.instanceOf(err, Error); done(); }); }); }); describe('fs.readFileSync(filename, [options])', function() { // this is provided by fs.openSync, fs.fstatSync, and fs.readSync // so more heavily tested elsewhere beforeEach(function() { mock({ 'path/to/file.txt': 'file content' }); }); afterEach(mock.restore); it('allows a file to be read synchronously', function() { var data = fs.readFileSync('path/to/file.txt'); assert.isTrue(Buffer.isBuffer(data)); assert.equal(String(data), 'file content'); }); it('fails for directory', function() { assert.throws(function() { fs.readFileSync('path/to'); }); }); it('fails for bad path', function() { assert.throws(function() { fs.readFileSync('path/to/bogus'); }); }); }); describe('fs.write(fd, buffer, offset, length, position, callback)', function() { beforeEach(function() { mock({ 'path/to/file.txt': 'file content' }); }); afterEach(mock.restore); it('writes a buffer to a file', function(done) { var fd = fs.openSync('path/new-file.txt', 'w'); var buffer = new Buffer('new file'); fs.write(fd, buffer, 0, buffer.length, null, function(err, written, buf) { if (err) { return done(err); } assert.equal(written, 8); assert.equal(buf, buffer); assert.equal(String(fs.readFileSync('path/new-file.txt')), 'new file'); done(); }); }); it('can write a portion of a buffer to a file', function(done) { fs.open('path/new-file.txt', 'w', function(err, fd) { if (err) { return done(err); } var buffer = new Buffer('new file'); fs.write(fd, buffer, 1, 5, null, function(err2, written, buf) { if (err2) { return done(err2); } assert.equal(written, 5); assert.equal(buf, buffer); assert.equal(String(fs.readFileSync('path/new-file.txt')), 'ew fi'); done(); }); }); }); it('can append to a file', function(done) { fs.open('path/to/file.txt', 'a', function(err, fd) { if (err) { return done(err); } var buffer = new Buffer(' more'); fs.write(fd, buffer, 0, 5, null, function(err2, written, buf) { if (err2) { return done(err2); } assert.equal(written, 5); assert.equal(buf, buffer); assert.equal(String(fs.readFileSync('path/to/file.txt')), 'file content more'); done(); }); }); }); it('fails if file not open for writing', function(done) { fs.open('path/to/file.txt', 'r', function(err, fd) { if (err) { return done(err); } fs.write(fd, new Buffer('oops'), 0, 4, null, function(err2) { assert.instanceOf(err2, Error); done(); }); }); }); }); describe('fs.writeSync(fd, buffer, offset, length, position)', function() { beforeEach(function() { mock({ 'path/to/file.txt': 'file content' }); }); afterEach(mock.restore); it('writes a buffer to a file', function() { var buffer = new Buffer('new file'); var fd = fs.openSync('path/new-file.txt', 'w'); var written = fs.writeSync(fd, buffer, 0, buffer.length); assert.equal(written, 8); assert.equal(String(fs.readFileSync('path/new-file.txt')), 'new file'); }); it('can write a portion of a buffer to a file', function() { var buffer = new Buffer('new file'); var fd = fs.openSync('path/new-file.txt', 'w'); var written = fs.writeSync(fd, buffer, 1, 5); assert.equal(written, 5); assert.equal(String(fs.readFileSync('path/new-file.txt')), 'ew fi'); }); it('can append to a file', function() { var buffer = new Buffer(' more'); var fd = fs.openSync('path/to/file.txt', 'a'); var written = fs.writeSync(fd, buffer, 0, 5); assert.equal(written, 5); assert.equal(String(fs.readFileSync('path/to/file.txt')), 'file content more'); }); it('fails if file not open for writing', function() { var fd = fs.openSync('path/to/file.txt', 'r'); assert.throws(function() { fs.writeSync(fd, new Buffer('oops'), 0, 4); }); }); }); describe('fs.write(fd, data[, position[, encoding]], callback)', function() { beforeEach(function() { mock({ 'path/to/file.txt': 'file content' }); }); afterEach(mock.restore); it('writes a string to a file', function(done) { fs.open('path/new-file.txt', 'w', function(err, fd) { if (err) { return done(err); } var string = 'new file'; fs.write(fd, string, null, 'utf-8', function(err