diff --git a/lib/index.js b/lib/index.js index 029aea74..d9ff6105 100644 --- a/lib/index.js +++ b/lib/index.js @@ -21,6 +21,8 @@ if (!fsName) { /** * Hijack the real fs module immediately so the binding can be swapped at will. + * This works as expected in cases where mock-fs is required before any other + * module that wraps fs exports. */ var mockFs = rewire(path.join(__dirname, '..', 'node', fsName)); var originalBinding = mockFs.__get__('binding'); @@ -36,24 +38,26 @@ function setBinding(binding, Stats) { /** - * Override the real fs module with the given configuration. Returns a function - * that can be called to restore the original file system. - * @param {Object} config File system configuration. - * @return {function()} Function called to restore the original file system. + * Swap out the fs bindings for a mock file system. + * @param {Object} config Mock file system configuration. */ -var exports = module.exports = function(config) { +var exports = module.exports = function mock(config) { var system = FileSystem.create(config); var binding = new Binding(system); setBinding(binding, binding.Stats); +}; + - return function restore() { - setBinding(originalBinding, originalStats); - }; +/** + * Restore the fs bindings for the real file system. + */ +exports.restore = function() { + setBinding(originalBinding, originalStats); }; /** - * Create a new fs module based on the given file system configuration. + * Create a mock fs module based on the given file system configuration. * @param {Object} config File system configuration. * @return {Object} A fs module with a mock file system. */ @@ -68,27 +72,10 @@ exports.fs = function(config) { // overwrite fs.Stats from original binding mockFs.Stats = binding.Stats; - // provide a method to reconfigure the file system - mockFs._reconfigure = function(opt_config) { - var newConfig = opt_config || config; - var newSystem = FileSystem.create(newConfig); - binding.setSystem(newSystem); - }; - return mockFs; }; -/** - * Initialize (or reinitialize) a file system. - * @param {Object} fs A mock fs module. - * @param {Object=} opt_config File system configuration. - */ -exports.init = function(fs, opt_config) { - fs._reconfigure(opt_config); -}; - - /** * Create a file factory. */ diff --git a/package.json b/package.json index 791cfb2a..deeedae6 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "mock-fs", - "description": "Mock fs implementation for testing", - "version": "1.3.1", + "description": "A configurable mock file system. You know, for testing.", + "version": "2.0.0-rc.1", "main": "lib/index.js", "homepage": "https://github.com/tschaub/mock-fs", "author": { @@ -12,7 +12,9 @@ "mock", "fs", "test", - "fixtures" + "fixtures", + "file system", + "memory" ], "repository": { "type": "git", diff --git a/readme.md b/readme.md index 390e1852..481118d8 100644 --- a/readme.md +++ b/readme.md @@ -1,15 +1,15 @@ # `mock-fs` -A configurable mock file system. You know, for testing. +The `mock-fs` module allows Node's built-in [`fs` module](http://nodejs.org/api/fs.html) to be backed temporarily by an in-memory, mock file system. This lets you run tests against a set of mock files and directories instead of lugging around a bunch of test fixtures. -## example +## Example The code below makes it so the `fs` module is temporarily backed by a mock file system with a few files and directories. ```js var mock = require('mock-fs'); -var restore = mock({ +mock({ 'path/to/fake/dir': { 'some-file.txt': 'file content here', 'empty-dir': {/** empty directory */} @@ -19,16 +19,37 @@ var restore = mock({ }); ``` -Note that the `mock` function returns a `restore` function. When you are ready to restore the `fs` module (so that it is backed by your real file system), call `restore()`. +When you are ready to restore the `fs` module (so that it is backed by your real file system), call [`mock.restore()`](#mockrestore). ```js // after a test runs -restore(); +mock.restore(); +``` + +## Docs + +### `mock(config)` + +Configure the `fs` module so it is backed by an in-memory file system. + +Calling `mock` sets up a mock file system with at least two directories: `process.cwd()` and `os.tmpdir()` (or `os.tmpDir()` for older Node). When called with no arguments, just these two directories are created. When called with a `config` object, additional files, directories, and symlinks are created. + +Property names of the `config` object are interpreted as relative paths to resources (relative from `process.cwd()`). Property values of the `config` object are interpreted as content or configuration for the generated resources. + +*Note that paths should always use forward slashes (`/`) - even on Windows.* + +### Creating files + +When `config` property values are a `string` or `Buffer`, a file is created with the provided content. For example, the following configuration creates a single file with string content (in addition to the two default directories). +```js +mock({ + 'path/to/file.txt': 'file content here' +}); ``` -## docs +To create a file with additional properties (owner, permissions, atime, etc.), use the [`mock.file()`](#mockfileproperties) function described below. -### `mock.file(properties)` +### `mock.file(properties)` Create a factory for new files. Supported properties: @@ -36,9 +57,9 @@ Create a factory for new files. Supported properties: * **mode** - `number` File mode (permission and sticky bits). Defaults to `0666`. * **uid** - `number` The user id. Defaults to `process.getuid()`. * **git** - `number` The group id. Defaults to `process.getgid()`. - * **atime** - `Date` The last file access time. - * **ctime** - `Date` The last file change time. - * **mtime** - `Date` The last file modification time. + * **atime** - `Date` The last file access time. Defaults to `Date.now()`. Updated when file contents are accessed. + * **ctime** - `Date` The last file change time. Defaults to `Date.now()`. Updated when file owner or permissions change. + * **mtime** - `Date` The last file modification time. Defaults to `Date.now()`. Updated when file contents change. To create a mock filesystem with a very old file named `foo`, you could do something like this: ```js @@ -51,16 +72,38 @@ mock({ }); ``` -### `mock.directory(properties)` +Note that if you want to create a file with the default properties, you can provide a `string` or `Buffer` directly instead of calling `mock.file()`. + +### Creating directories + +When `config` property values are an `Object`, a directory is created. The structure of the object is the same as the `config` object itself. So an empty directory can be created with a simple object literal (`{}`). The following configuration creates a directory containing two files (in addition to the two default directories): +```js +// note that this could also be written as +// mock({'path/to/dir': { /** config */ }}) +mock({ + path: { + to: { + dir: { + file1: 'text content', + file2: new Buffer([1, 2, 3, 4]) + } + } + } +}); +``` + +To create a directory with additional properties (owner, permissions, atime, etc.), use the [`mock.directory()`](mockdirectoryproperties) function described below. + +### `mock.directory(properties)` Create a factory for new directories. Supported properties: * **mode** - `number` Directory mode (permission and sticky bits). Defaults to `0777`. * **uid** - `number` The user id. Defaults to `process.getuid()`. * **git** - `number` The group id. Defaults to `process.getgid()`. - * **atime** - `Date` The last directory access time. - * **ctime** - `Date` The last directory change time. - * **mtime** - `Date` The last directory modification time. + * **atime** - `Date` The last directory access time. Defaults to `Date.now()`. + * **ctime** - `Date` The last directory change time. Defaults to `Date.now()`. Updated when owner or permissions change. + * **mtime** - `Date` The last directory modification time. Defaults to `Date.now()`. * **items** - `Object` Directory contents. Members will generate additional files, directories, or symlinks. To create a mock filesystem with a directory with the relative path `some/dir` that has a mode of `0755` and a couple child files, you could do something like this: @@ -76,7 +119,13 @@ mock({ }); ``` -### `mock.symlink(properties)` +Note that if you want to create a directory with the default properties, you can provide an `Object` directly instead of calling `mock.directory()`. + +### Creating symlinks + +Using a `string` or a `Buffer` is a shortcut for creating files with default properties. Using an `Object` is a shortcut for creating a directory with default properties. There is no shortcut for creating symlinks. To create a symlink, you need to call the [`mock.symlink()`](#mocksymlinkproperties) function described below. + +### `mock.symlink(properties)` Create a factory for new symlinks. Supported properties: @@ -84,9 +133,9 @@ Create a factory for new symlinks. Supported properties: * **mode** - `number` Symlink mode (permission and sticky bits). Defaults to `0666`. * **uid** - `number` The user id. Defaults to `process.getuid()`. * **git** - `number` The group id. Defaults to `process.getgid()`. - * **atime** - `Date` The last symlink access time. - * **ctime** - `Date` The last symlink change time. - * **mtime** - `Date` The last symlink modification time. + * **atime** - `Date` The last symlink access time. Defaults to `Date.now()`. + * **ctime** - `Date` The last symlink change time. Defaults to `Date.now()`. + * **mtime** - `Date` The last symlink modification time. Defaults to `Date.now()`. To create a mock filesystem with a file and a symlink, you could do something like this: ```js @@ -100,7 +149,28 @@ mock({ }); ``` -## install +### Restoring the file system + +### `mock.restore()` + +Restore the `fs` binding to the real file system. This undoes the effect of calling `mock()`. Typically, you would set up a mock file system before running a test and restore the original after. Using a test runner with `beforeEach` and `afterEach` hooks, this might look like the following: + +```js +beforeEach(function() { + mock({ + 'fake-file': 'file contents' + }); +}); +afterEach(mock.restore); +``` + +### Creating a new `fs` module instead of modifying the original + +### `mock.fs(config)` + +Calling `mock()` modifies Node's built-in `fs` module. This is useful when you want to test with a mock file system. If for some reason you want to work with the real file system and an in-memory version at the same time, you can call the `mock.fs()` function. This takes the same `config` object [described above](#mockconfig) and sets up a in-memory file system. Instead of modifying the binding for the built-in `fs` module (as is done when calling `mock(config)`), the `mock.fs(config)` function returns an object with the same interface as the `fs` module, but backed by your mock file system. + +## Install Using `npm`: @@ -108,11 +178,11 @@ Using `npm`: npm install mock-fs --save-dev ``` -## caveats +## Caveats When you require `mock-fs`, Node's own `fs` module is patched to allow the binding to the underlying file system to be swapped out. If you require `mock-fs` *before* any other modules that modify `fs` (e.g. `graceful-fs`), the mock should behave as expected. -The following `fs` functions are overridden: `fs.ReadStream`, `fs.Stats`, `fs.WriteStream`, `fs.appendFile`, `fs.appendFileSync`, `fs.chmod`, `fs.chmodSync`, `fs.chown`, `fs.chownSync`, `fs.close`, `fs.closeSync`, `fs.createReadStream`, `fs.createWriteStream`, `fs.exists`, `fs.existsSync`, `fs.fchmod`, `fs.fchmodSync`, `fs.fchown`, `fs.fchownSync`, `fs.fdatasync`, `fs.fdatasyncSync`, `fs.fstat`, `fs.fstatSync`, `fs.fsync`, `fs.fsyncSync`, `fs.ftruncate`, `fs.ftruncateSync`, `fs.futimes`, `fs.futimesSync`, `fs.lchmod`, `fs.lchmodSync`, `fs.lchown`, `fs.lchownSync`, `fs.link`, `fs.linkSync`, `fs.lstatSync`, `fs.lstat`, `fs.mkdir`, `fs.mkdirSync`, `fs.open`, `fs.openSync`, `fs.read`, `fs.readSync`, `fs.readFile`, `fs.readFileSync`, `fs.readdir`, `fs.readdirSync`, `fs.readlink`, `fs.readlinkSync`, `fs.realpath`, `fs.realpathSync`, `fs.rename`, `fs.renameSync`, `fs.rmdir`, `fs.rmdirSync`, `fs.stat`, `fs.statSync`, `fs.symlink`, `fs.symlinkSync`, `fs.truncate`, `fs.truncateSync`, `fs.unlink`, `fs.unlinkSync`, `fs.utimes`, `fs.utimesSync`, `fs.write`, `fs.writeSync`, `fs.writeFile`, and `fs.writeFileSync`. +The following [`fs` functions](http://nodejs.org/api/fs.html) are overridden: `fs.ReadStream`, `fs.Stats`, `fs.WriteStream`, `fs.appendFile`, `fs.appendFileSync`, `fs.chmod`, `fs.chmodSync`, `fs.chown`, `fs.chownSync`, `fs.close`, `fs.closeSync`, `fs.createReadStream`, `fs.createWriteStream`, `fs.exists`, `fs.existsSync`, `fs.fchmod`, `fs.fchmodSync`, `fs.fchown`, `fs.fchownSync`, `fs.fdatasync`, `fs.fdatasyncSync`, `fs.fstat`, `fs.fstatSync`, `fs.fsync`, `fs.fsyncSync`, `fs.ftruncate`, `fs.ftruncateSync`, `fs.futimes`, `fs.futimesSync`, `fs.lchmod`, `fs.lchmodSync`, `fs.lchown`, `fs.lchownSync`, `fs.link`, `fs.linkSync`, `fs.lstatSync`, `fs.lstat`, `fs.mkdir`, `fs.mkdirSync`, `fs.open`, `fs.openSync`, `fs.read`, `fs.readSync`, `fs.readFile`, `fs.readFileSync`, `fs.readdir`, `fs.readdirSync`, `fs.readlink`, `fs.readlinkSync`, `fs.realpath`, `fs.realpathSync`, `fs.rename`, `fs.renameSync`, `fs.rmdir`, `fs.rmdirSync`, `fs.stat`, `fs.statSync`, `fs.symlink`, `fs.symlinkSync`, `fs.truncate`, `fs.truncateSync`, `fs.unlink`, `fs.unlinkSync`, `fs.utimes`, `fs.utimesSync`, `fs.write`, `fs.writeSync`, `fs.writeFile`, and `fs.writeFileSync`. Mock `fs.Stats` objects have the following properties: `dev`, `ino`, `nlink`, `mode`, `size`, `rdev`, `blksize`, `blocks`, `atime`, `ctime`, `mtime`, `uid`, and `gid`. In addition, all of the `is*()` method are provided (e.g. `isDirectory()`, `isFile()`, et al.). diff --git a/test/integration/filecount.spec.js b/test/integration/filecount.spec.js index e33686c3..ab156271 100644 --- a/test/integration/filecount.spec.js +++ b/test/integration/filecount.spec.js @@ -5,9 +5,8 @@ var count = require('./filecount'); describe('count(dir, callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/dir': { 'one.txt': 'first file', 'two.txt': 'second file', @@ -18,9 +17,7 @@ describe('count(dir, callback)', function() { } }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('counts files in a directory', function(done) { diff --git a/test/lib/index.spec.js b/test/lib/index.spec.js index 03447764..b8835c71 100644 --- a/test/lib/index.spec.js +++ b/test/lib/index.spec.js @@ -9,23 +9,27 @@ describe('The API', function() { describe('mock()', function() { it('configures the real fs module with a mock file system', function() { - var restore = mock({ + mock({ 'fake-file-for-testing-only': 'file content' }); assert.isTrue(fs.existsSync('fake-file-for-testing-only')); - restore(); + mock.restore(); }); - it('returns a function for restoring the real fs', function() { - var restore = mock({ + }); + + 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')); - restore(); + mock.restore(); assert.isFalse(fs.existsSync('fake-file-for-testing-only')); }); @@ -33,14 +37,11 @@ describe('The API', function() { describe('mock.file()', function() { - var restore; - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('lets you create files with additional properties', function(done) { - restore = mock({ + mock({ 'path/to/file.txt': mock.file({ content: 'file content', mtime: new Date(8675309), @@ -65,14 +66,11 @@ describe('The API', function() { describe('mock.directory()', function() { - var restore; - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('lets you create directories with more properties', function(done) { - restore = mock({ + mock({ 'path/to/dir': mock.directory({ mtime: new Date(8675309), mode: 0644 @@ -96,14 +94,11 @@ describe('The API', function() { describe('mock.symlink()', function() { - var restore; - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('lets you create symbolic links', function() { - restore = mock({ + mock({ 'path/to/file': 'content', 'path/to/link': mock.symlink({path: './file'}) }); @@ -151,52 +146,14 @@ describe('The API', function() { }); - describe('mock.init()', function() { - - it('provides a method to reconfigure the mock file system', function() { - - var mockFs = mock.fs({ - 'first-file.txt': 'file content' - }); - assert.isTrue(mockFs.existsSync('first-file.txt')); - - mock.init(mockFs, { - 'second-file.txt': 'new content' - }); - - assert.isFalse(mockFs.existsSync('first-file.txt')); - assert.isTrue(mockFs.existsSync('second-file.txt')); - - }); - - it('uses initial config if called with no args', function() { - - var mockFs = mock.fs({ - 'first-file.txt': 'file content' - }); - assert.isTrue(mockFs.existsSync('first-file.txt')); - - mockFs.unlinkSync('first-file.txt'); - assert.isFalse(mockFs.existsSync('first-file.txt')); - - // restore initial configuration - mock.init(mockFs); - assert.isTrue(mockFs.existsSync('first-file.txt')); - - }); - - }); - }); - describe('Mocking the file system', function() { describe('fs.rename(oldPath, newPath, callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/a.bin': new Buffer([1, 2, 3]), 'empty': {}, 'nested': { @@ -206,9 +163,7 @@ describe('Mocking the file system', function() { } }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('allows files to be renamed', function(done) { fs.rename('path/to/a.bin', 'path/to/b.bin', function(err) { @@ -256,9 +211,8 @@ describe('Mocking the file system', function() { describe('fs.renameSync(oldPath, newPath)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/a.bin': new Buffer([1, 2, 3]), 'empty': {}, 'nested': { @@ -269,9 +223,7 @@ describe('Mocking the file system', function() { 'link': mock.symlink({path: './path/to/a.bin'}) }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('allows files to be renamed', function() { fs.renameSync('path/to/a.bin', 'path/to/b.bin'); @@ -328,9 +280,8 @@ describe('Mocking the file system', function() { describe('fs.stat(path, callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ '/path/to/file.txt': mock.file({ ctime: new Date(1), mtime: new Date(2), @@ -342,9 +293,7 @@ describe('Mocking the file system', function() { '/empty': {} }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('creates an instance of fs.Stats', function(done) { @@ -424,16 +373,13 @@ describe('Mocking the file system', function() { describe('fs.fstat(fd, callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/file.txt': 'file content', 'empty': {} }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('accepts a file descriptor for a file (r)', function(done) { @@ -478,16 +424,13 @@ describe('Mocking the file system', function() { describe('fs.fstatSync(fd)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/file.txt': 'file content', 'empty': {} }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('accepts a file descriptor for a file (r)', function() { @@ -521,9 +464,8 @@ describe('Mocking the file system', function() { describe('fs.exists(path, callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/a.bin': new Buffer([1, 2, 3]), 'empty': {}, 'nested': { @@ -533,9 +475,7 @@ describe('Mocking the file system', function() { } }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('calls with true if file exists', function(done) { fs.exists(path.join('path', 'to', 'a.bin'), function(exists) { @@ -598,9 +538,8 @@ describe('Mocking the file system', function() { describe('fs.existsSync(path)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/a.bin': new Buffer([1, 2, 3]), 'empty': {}, 'nested': { @@ -610,9 +549,7 @@ describe('Mocking the file system', function() { } }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('returns true if file exists', function() { assert.isTrue(fs.existsSync(path.join('path', 'to', 'a.bin'))); @@ -650,9 +587,8 @@ describe('Mocking the file system', function() { describe('fs.readdirSync(path)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/file.txt': 'file content', 'nested': { 'sub': { @@ -665,9 +601,7 @@ describe('Mocking the file system', function() { } }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('lists directory contents', function() { var items = fs.readdirSync(path.join('path', 'to')); @@ -692,9 +626,8 @@ describe('Mocking the file system', function() { describe('fs.readdir(path, callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/file.txt': 'file content', 'nested': { 'sub': { @@ -707,9 +640,7 @@ describe('Mocking the file system', function() { } }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('lists directory contents', function(done) { fs.readdir(path.join('path', 'to'), function(err, items) { @@ -741,9 +672,8 @@ describe('Mocking the file system', function() { describe('fs.readdirSync(path)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/file.txt': 'file content', 'nested': { 'sub': { @@ -756,9 +686,7 @@ describe('Mocking the file system', function() { } }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('lists directory contents', function() { var items = fs.readdirSync(path.join('path', 'to')); @@ -782,9 +710,8 @@ describe('Mocking the file system', function() { describe('fs.open(path, flags, [mode], callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/file.txt': 'file content', 'nested': { 'sub': { @@ -797,9 +724,7 @@ describe('Mocking the file system', function() { } }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('opens an existing file for reading (r)', function(done) { fs.open('nested/sub/dir/one.txt', 'r', function(err, fd) { @@ -853,9 +778,8 @@ describe('Mocking the file system', function() { describe('fs.openSync(path, flags, [mode])', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/file.txt': 'file content', 'nested': { 'sub': { @@ -868,9 +792,7 @@ describe('Mocking the file system', function() { } }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('opens an existing file for reading (r)', function() { var fd = fs.openSync('path/to/file.txt', 'r'); @@ -904,13 +826,10 @@ describe('Mocking the file system', function() { describe('fs.close(fd, callback)', function() { - var restore; beforeEach(function() { - restore = mock({'dir': {}}); - }); - afterEach(function() { - restore(); + mock({'dir': {}}); }); + afterEach(mock.restore); it('closes a file descriptor', function(done) { var fd = fs.openSync('dir/file.txt', 'w'); @@ -936,13 +855,10 @@ describe('Mocking the file system', function() { describe('fs.closeSync(fd)', function() { - var restore; beforeEach(function() { - restore = mock({'dir': {}}); - }); - afterEach(function() { - restore(); + mock({'dir': {}}); }); + afterEach(mock.restore); it('closes a file descriptor', function() { var fd = fs.openSync('dir/file.txt', 'w'); @@ -962,15 +878,12 @@ describe('Mocking the file system', function() { var readSig = 'fs.read(fd, buffer, offset, length, position, callback)'; describe(readSig, function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/file.txt': 'file content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('allows file contents to be read', function(done) { fs.open('path/to/file.txt', 'r', function(err, fd) { @@ -1103,15 +1016,12 @@ describe('Mocking the file system', function() { describe('fs.readSync(fd, buffer, offset, length, position)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/file.txt': 'file content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('allows a file to be read synchronously', function() { @@ -1159,15 +1069,12 @@ describe('Mocking the file system', function() { // this is provided by fs.open, fs.fstat, and fs.read // so more heavily tested elsewhere - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/file.txt': 'file content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('allows a file to be read asynchronously', function(done) { fs.readFile('path/to/file.txt', function(err, data) { @@ -1201,15 +1108,12 @@ describe('Mocking the file system', function() { // this is provided by fs.openSync, fs.fstatSync, and fs.readSync // so more heavily tested elsewhere - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/file.txt': 'file content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('allows a file to be read synchronously', function() { var data = fs.readFileSync('path/to/file.txt'); @@ -1234,15 +1138,12 @@ describe('Mocking the file system', function() { var fsWrite = 'fs.write(fd, buffer, offset, length, position, callback)'; describe(fsWrite, function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/file.txt': 'file content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('writes a buffer to a file', function(done) { var fd = fs.openSync('path/new-file.txt', 'w'); @@ -1313,15 +1214,12 @@ describe('Mocking the file system', function() { describe('fs.writeSync(fd, buffer, offset, length, position)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/file.txt': 'file content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('writes a buffer to a file', function() { var buffer = new Buffer('new file'); @@ -1361,15 +1259,12 @@ describe('Mocking the file system', function() { describe('fs.write(fd, data[, position[, encoding]], callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/file.txt': 'file content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('writes a string to a file', function(done) { fs.open('path/new-file.txt', 'w', function(err, fd) { @@ -1425,15 +1320,12 @@ describe('Mocking the file system', function() { describe('fs.writeSync(fd, data[, position[, encoding]])', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/file.txt': 'file content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('writes a string to a file', function() { var fd = fs.openSync('path/new-file.txt', 'w'); @@ -1462,15 +1354,12 @@ describe('Mocking the file system', function() { describe('fs.writeFile(filename, data, [options], callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ '.': {} }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('writes a string to a file', function(done) { fs.writeFile('foo', 'bar', function(err) { @@ -1503,15 +1392,12 @@ describe('Mocking the file system', function() { describe('fs.writeFileSync(filename, data, [options]', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ '.': {} }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('writes a string to a file', function() { fs.writeFileSync('foo', 'bar'); @@ -1533,16 +1419,13 @@ describe('Mocking the file system', function() { describe('fs.appendFile(filename, data, [options], callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'dir/file.txt': 'file content', 'link.txt': mock.symlink({path: 'dir/file.txt'}) }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('writes a string to a new file', function(done) { fs.appendFile('foo', 'bar', function(err) { @@ -1598,15 +1481,12 @@ describe('Mocking the file system', function() { describe('fs.appendFileSync(filename, data, [options]', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/file': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('writes a string to a new file', function() { fs.appendFileSync('foo', 'bar'); @@ -1628,15 +1508,12 @@ describe('Mocking the file system', function() { describe('fs.mkdir(path, [mode], callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'parent': {} }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('creates a new directory', function(done) { fs.mkdir('parent/dir', function(err) { @@ -1679,16 +1556,13 @@ describe('Mocking the file system', function() { describe('fs.mkdirSync(path, [mode])', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'parent': {}, 'file.txt': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('creates a new directory', function() { fs.mkdirSync('parent/dir'); @@ -1725,15 +1599,12 @@ describe('Mocking the file system', function() { describe('fs.rmdir(path, callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/to/empty': {} }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('removes an empty directory', function(done) { assert.equal(fs.statSync('path/to').nlink, 3); @@ -1759,16 +1630,13 @@ describe('Mocking the file system', function() { describe('fs.rmdirSync(path)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/empty': {}, 'file.txt': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('removes an empty directory', function() { fs.rmdirSync('path/empty'); @@ -1797,16 +1665,13 @@ describe('Mocking the file system', function() { describe('fs.chown(path, uid, gid, callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/empty': {}, 'file.txt': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('changes ownership of a file', function(done) { fs.chown('file.txt', 42, 43, done); @@ -1823,16 +1688,13 @@ describe('Mocking the file system', function() { describe('fs.chownSync(path, uid, gid)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/empty': {}, 'file.txt': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('changes ownership of a file', function() { fs.chownSync('file.txt', 42, 43); @@ -1848,16 +1710,13 @@ describe('Mocking the file system', function() { describe('fs.fchown(fd, uid, gid, callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/empty': {}, 'file.txt': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('changes ownership of a file', function(done) { var fd = fs.openSync('file.txt', 'r'); @@ -1868,16 +1727,13 @@ describe('Mocking the file system', function() { describe('fs.fchownSync(fd, uid, gid)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'path/empty': {}, 'file.txt': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('changes ownership of a file', function() { var fd = fs.openSync('file.txt', 'r'); @@ -1888,15 +1744,12 @@ describe('Mocking the file system', function() { describe('fs.chmod(path, mode, callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'file.txt': mock.file({mode: 0644}) }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('changes permissions of a file', function(done) { fs.chmod('file.txt', 0664, function(err) { @@ -1920,15 +1773,12 @@ describe('Mocking the file system', function() { describe('fs.chmodSync(path, mode)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'file.txt': mock.file({mode: 0666}) }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('changes permissions of a file', function() { fs.chmodSync('file.txt', 0644); @@ -1946,15 +1796,12 @@ describe('Mocking the file system', function() { describe('fs.fchmod(fd, mode, callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'file.txt': mock.file({mode: 0666}) }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('changes permissions of a file', function(done) { var fd = fs.openSync('file.txt', 'r'); @@ -1972,15 +1819,12 @@ describe('Mocking the file system', function() { describe('fs.fchmodSync(fd, mode)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'file.txt': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('changes permissions of a file', function() { var fd = fs.openSync('file.txt', 'r'); @@ -1993,16 +1837,13 @@ describe('Mocking the file system', function() { describe('fs.unlink(path, callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'dir': {}, 'file.txt': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('deletes a file', function(done) { fs.unlink('file.txt', function(err) { @@ -2042,15 +1883,12 @@ describe('Mocking the file system', function() { describe('fs.unlinkSync(path)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'file.txt': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('deletes a file', function() { fs.unlinkSync('file.txt'); @@ -2072,16 +1910,13 @@ describe('Mocking the file system', function() { describe('fs.utimes(path, atime, mtime, callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'dir': {}, 'file.txt': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('updates timestamps for a file', function(done) { fs.utimes('file.txt', new Date(100), new Date(200), function(err) { @@ -2118,15 +1953,12 @@ describe('Mocking the file system', function() { describe('fs.utimesSync(path, atime, mtime)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'file.txt': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('updates timestamps for a file', function() { fs.utimesSync('file.txt', new Date(100), new Date(200)); @@ -2139,16 +1971,13 @@ describe('Mocking the file system', function() { describe('fs.futimes(fd, atime, mtime, callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'dir': {}, 'file.txt': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('updates timestamps for a file', function(done) { var fd = fs.openSync('file.txt', 'r'); @@ -2180,15 +2009,12 @@ describe('Mocking the file system', function() { describe('fs.futimesSync(path, atime, mtime)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'file.txt': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('updates timestamps for a file', function() { var fd = fs.openSync('file.txt', 'r'); @@ -2202,16 +2028,13 @@ describe('Mocking the file system', function() { describe('fs.link(srcpath, dstpath, callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'dir': {}, 'file.txt': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('creates a link to a file', function(done) { assert.equal(fs.statSync('file.txt').nlink, 1); @@ -2268,15 +2091,12 @@ describe('Mocking the file system', function() { describe('fs.linkSync(srcpath, dstpath)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'file.txt': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('creates a link to a file', function() { fs.linkSync('file.txt', 'link.txt'); @@ -2308,16 +2128,13 @@ describe('Mocking the file system', function() { describe('fs.symlink(srcpath, dstpath, [type], callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'dir': {}, 'file.txt': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('creates a symbolic link to a file', function(done) { fs.symlink('../file.txt', 'dir/link.txt', function(err) { @@ -2356,16 +2173,13 @@ describe('Mocking the file system', function() { describe('fs.symlinkSync(srcpath, dstpath, [type])', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'dir': {}, 'file.txt': 'content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('creates a symbolic link to a file', function() { fs.symlinkSync('../file.txt', 'dir/link.txt'); @@ -2389,16 +2203,13 @@ describe('Mocking the file system', function() { describe('fs.readlink(path, callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'file.txt': 'content', 'link': mock.symlink({path: './file.txt'}) }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('reads a symbolic link', function(done) { fs.readlink('link', function(err, srcPath) { @@ -2421,16 +2232,13 @@ describe('Mocking the file system', function() { describe('fs.readlinkSync(path)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'file.txt': 'content', 'link': mock.symlink({path: './file.txt'}) }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('reads a symbolic link', function() { assert.equal(fs.readlinkSync('link'), './file.txt'); @@ -2446,9 +2254,8 @@ describe('Mocking the file system', function() { describe('fs.lstat(path, callback)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'file.txt': mock.file({ content: 'content', mtime: new Date(1) @@ -2459,9 +2266,7 @@ describe('Mocking the file system', function() { }) }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('stats a symbolic link', function(done) { fs.lstat('link', function(err, stats) { @@ -2491,9 +2296,8 @@ describe('Mocking the file system', function() { describe('fs.lstatSync(path)', function() { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'file.txt': mock.file({ content: 'content', mtime: new Date(1) @@ -2504,9 +2308,7 @@ describe('Mocking the file system', function() { }) }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('stats a symbolic link', function() { var stats = fs.lstatSync('link'); @@ -2528,16 +2330,13 @@ describe('Mocking the file system', function() { // based on binding.lstat and binding.readlink so tested elsewhere as well - var restore; beforeEach(function() { - restore = mock({ + mock({ 'dir/file.txt': 'content', 'link': mock.symlink({path: './dir/file.txt'}) }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('resolves the real path for a symbolic link', function(done) { @@ -2567,15 +2366,12 @@ describe('Mocking the file system', function() { describe('fs.createReadStream(path, [options])', function(done) { - var restore; beforeEach(function() { - restore = mock({ + mock({ 'dir/source': 'source content' }); }); - afterEach(function() { - restore(); - }); + afterEach(mock.restore); it('creates a readable stream', function() {