Giter Club home page Giter Club logo

mock-fs's Introduction

Build Status

mock-fs

The mock-fs module allows Node's built-in fs module 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

The code below makes it so the fs module is temporarily backed by a mock file system with a few files and directories.

const mock = require('mock-fs');

mock({
  'path/to/fake/dir': {
    'some-file.txt': 'file content here',
    'empty-dir': {/** empty directory */}
  },
  'path/to/some.png': Buffer.from([8, 6, 7, 5, 3, 0, 9]),
  'some/other/path': {/** another empty directory */}
});

When you are ready to restore the fs module (so that it is backed by your real file system), call mock.restore(). Note that calling this may be mandatory in some cases. See istanbuljs/nyc#324

// after a test runs
mock.restore();

Upgrading to version 4

Instead of overriding all methods of the built-in fs module, the library now overrides process.binding('fs'). The purpose of this change is to avoid conflicts with other libraries that override fs methods (e.g. graceful-fs) and to make it possible to work with multiple Node releases without maintaining copied and slightly modified versions of Node's fs module.

Breaking changes:

  • The mock.fs() function has been removed. This returned an object with fs-like methods without overriding the built-in fs module.
  • The object created by fs.Stats is no longer an instance of fs.Stats (though it has all the same properties and methods).
  • Lazy require() do not use the real filesystem.
  • Tests are no longer run in Node < 4.

Some of these breaking changes may be restored in a future release.

Docs

Configure the fs module so it is backed by an in-memory file system.

Calling mock sets up a mock file system with two directories by default: 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. To avoid creating a directory for process.cwd() and os.tmpdir(), see the options below.

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.

The second (optional) argument may include the properties below.

  • createCwd - boolean Create a directory for process.cwd(). This is true by default.
  • createTmp - boolean Create a directory for os.tmpdir(). This is true by default.

Loading real files & directories

You can load real files and directories into the mock system using mock.load()

Notes

  • All stat information is duplicated (dates, permissions, etc)
  • By default, all files are lazy-loaded, unless you specify the {lazy: false} option
Option Type Default Description
lazy boolean true File content isn't loaded until explicitly read
recursive boolean true Load all files and directories recursively

mock.load(path, options)

mock({
  // Lazy-load file
  'my-file.txt': mock.load(path.resolve(__dirname, 'assets/special-file.txt')),
  
  // Pre-load js file
  'ready.js': mock.load(path.resolve(__dirname, 'scripts/ready.js'), {lazy: false}),

  // Recursively loads all node_modules
  'node_modules': mock.load(path.resolve(__dirname, '../node_modules')),

  // Creates a directory named /tmp with only the files in /tmp/special_tmp_files (no subdirectories), pre-loading all content
  '/tmp': mock.load('/tmp/special_tmp_files', {recursive: false, lazy:false}),

  'fakefile.txt': 'content here'
});

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).

mock({
  'path/to/file.txt': 'file content here'
});

To create a file with additional properties (owner, permissions, atime, etc.), use the mock.file() function described below.

Create a factory for new files. Supported properties:

  • content - string|Buffer File contents.
  • mode - number File mode (permission and sticky bits). Defaults to 0666.
  • uid - number The user id. Defaults to process.getuid().
  • gid - number The group id. Defaults to process.getgid().
  • atime - Date The last file access time. Defaults to new Date(). Updated when file contents are accessed.
  • ctime - Date The last file change time. Defaults to new Date(). Updated when file owner or permissions change.
  • mtime - Date The last file modification time. Defaults to new Date(). Updated when file contents change.
  • birthtime - Date The time of file creation. Defaults to new Date().

To create a mock filesystem with a very old file named foo, you could do something like this:

mock({
  foo: mock.file({
    content: 'file content here',
    ctime: new Date(1),
    mtime: new Date(1)
  })
});

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):

// note that this could also be written as
// mock({'path/to/dir': { /** config */ }})
mock({
  path: {
    to: {
      dir: {
        file1: 'text content',
        file2: Buffer.from([1, 2, 3, 4])
      }
    }
  }
});

To create a directory with additional properties (owner, permissions, atime, etc.), use the mock.directory() function described below.

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().
  • gid - number The group id. Defaults to process.getgid().
  • atime - Date The last directory access time. Defaults to new Date().
  • ctime - Date The last directory change time. Defaults to new Date(). Updated when owner or permissions change.
  • mtime - Date The last directory modification time. Defaults to new Date(). Updated when an item is added, removed, or renamed.
  • birthtime - Date The time of directory creation. Defaults to new Date().
  • 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 two child files, you could do something like this:

mock({
  'some/dir': mock.directory({
    mode: 0755,
    items: {
      file1: 'file one content',
      file2: Buffer.from([8, 6, 7, 5, 3, 0, 9])
    }
  })
});

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() function described below.

Create a factory for new symlinks. Supported properties:

  • path - string Path to the source (required).
  • mode - number Symlink mode (permission and sticky bits). Defaults to 0666.
  • uid - number The user id. Defaults to process.getuid().
  • gid - number The group id. Defaults to process.getgid().
  • atime - Date The last symlink access time. Defaults to new Date().
  • ctime - Date The last symlink change time. Defaults to new Date().
  • mtime - Date The last symlink modification time. Defaults to new Date().
  • birthtime - Date The time of symlink creation. Defaults to new Date().

To create a mock filesystem with a file and a symlink, you could do something like this:

mock({
  'some/dir': {
    'regular-file': 'file contents',
    'a-symlink': mock.symlink({
      path: 'regular-file'
    })
  }
});

Restoring the file system

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:

beforeEach(function() {
  mock({
    'fake-file': 'file contents'
  });
});
afterEach(mock.restore);

Bypassing the mock file system

Execute calls to the real filesystem with mock.bypass()

// This file exists only on the real FS, not on the mocked FS
const realFilePath = '/path/to/real/file.txt';
const myData = mock.bypass(() => fs.readFileSync(realFilePath, 'utf-8'));

If you pass an asynchronous function or a promise-returning function to bypass(), a promise will be returned.

Asynchronous calls are supported, however, they are not recommended as they could produce unintended consequences if anything else tries to access the mocked filesystem before they've completed.

async function getFileInfo(fileName) {
  return await mock.bypass(async () => {
    const stats = await fs.promises.stat(fileName);
    const data = await fs.promises.readFile(fileName);
    return {stats, data};
  });
}

Install

Using npm:

npm install mock-fs --save-dev

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.

Note mock-fs is not compatible with [email protected] but works with [email protected].

Mock file access is controlled based on file mode where process.getuid() and process.getgid() are available (POSIX systems). On other systems (e.g. Windows) the file mode has no effect.

Tested on Linux, OSX, and Windows using Node 12 through 16. Check the tickets for a list of known issues.

Using with Jest Snapshot Testing

.toMatchSnapshot in Jest uses fs to load existing snapshots. If mockFs is active, Jest isn't able to load existing snapshots. In such case it accepts all snapshots without diffing the old ones, which breaks the concept of snapshot testing.

Calling mock.restore() in afterEach is too late and it's necessary to call it before snapshot matching:

const actual = testedFunction()
mock.restore()
expect(actual).toMatchSnapshot()

Note: it's safe to call mock.restore multiple times, so it can still be called in afterEach and then manually in test cases which use snapshot testing.

mock-fs's People

Contributors

3cp avatar agrzes avatar caitp avatar ciaranj avatar dependabot[bot] avatar deployable avatar floatdrop avatar goliney avatar greenkeeperio-bot avatar igorminar avatar jloleysens avatar justblackbird avatar jwilsson avatar matheuss avatar maxwellgerber avatar meandmycode avatar mrmlnc avatar mutantcornholio avatar nonara avatar not-an-aardvark avatar psalaets avatar rugvip avatar shyiko avatar tillig avatar timkendrick avatar tmcw avatar tomhughes avatar tricoder42 avatar tschaub avatar vlindhol avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mock-fs's Issues

Issue Reading Created Symlink

In the example below I create a symlink in an empty directory, I can see that the file is there, and registers as a symlink, I just can't read it.

Thoughts?

var chai = require("chai")
var expect = chai.expect

var mock = require("mock-fs")

var fs = require("fs")

describe("mock-fs", function(){
  beforeEach(function(){
    mock({
      'file.txt': 'file content',
      'empty-dir': {}
    })
  })
  afterEach(function() {
    mock.restore()
  })
  it("should create readable symlink", function(){
    fs.symlinkSync("file.txt", "empty-dir/symlink.txt")
    expect(fs.readdirSync("empty-dir")).to.contain("symlink.txt") // ✓
    expect(fs.lstatSync("empty-dir/symlink.txt").isSymbolicLink()).to.equal(true) // ✓
    expect(fs.readFileSync("empty-dir/symlink.txt", "utf8")).to.equal("file content") // ×
  })
})

mocking image files

I am testing module that loads/saves images from files in PNG, JPEG and other formats.

Image fixtures can be stored

  • on real file system in test fixtures directory
  • on mocked file system using mock-fs

With the the second option I have problem: How can I generate random file content in JPEG/PNG format? For example:

'/var/files/my.jpg': mockFs.file({
   content: faker.image(...,'JPEG',....)
})

Is there faker modules for Node.js?

mock-fs does not work with node 0.11.15

Test file test.js:

const mock = require('mock-fs');
const fs = require('fs');

fs.createReadStream('test.js');

Throws:

Assertion failed: (object->InternalFieldCount() > 0), function Wrap, file ../src/util-inl.h, line 106.
[1]    6085 abort      node test.js

Runtime error when using mock-fs and express.js body-parser

I'm testing my express.js middleware with mock-fs to mock files that should be read or written.

It seems that using mock-fs in my tests breaks the express.js body-parser package.

I created a Gist to reproduce the issue: https://gist.github.com/mlenkeit/a6fa3960967b3fa6a165
Simply clone the Gist, run npm install followed by npm test. The tests will fail somewhere deep in the body-parser package. If you comment mocking the filesystem in the Gist (lines 19 and 23) and run the tests again, everything works fine.

I attached a stack trace (which doesn't include any sign of mock-fs).

Stack trace:

Error: specified encoding unsupported
    at makeError (c:\github\a6fa3960967b3fa6a165\node_modules\body-parser\node_modules\raw-body\index.js:184:15)
    at getDecoder (c:\github\a6fa3960967b3fa6a165\node_modules\body-parser\node_modules\raw-body\index.js:156:15)
    at module.exports (c:\github\a6fa3960967b3fa6a165\node_modules\body-parser\node_modules\raw-body\index.js:75:15)
    at read (c:\github\a6fa3960967b3fa6a165\node_modules\body-parser\lib\read.js:62:3)
    at urlencodedParser (c:\github\a6fa3960967b3fa6a165\node_modules\body-parser\lib\types\urlencoded.js:83:5)
    at Layer.handle [as handle_request] (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:312:13)
    at c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:280:7
    at Function.process_params (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:330:12)
    at next (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:271:10)
    at expressInit (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\middleware\init.js:33:5)
    at Layer.handle [as handle_request] (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:312:13)
    at c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:280:7
    at Function.process_params (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:330:12)
    at next (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:271:10)
    at query (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\middleware\query.js:38:5)
    at Layer.handle [as handle_request] (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:312:13)
    at c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:280:7
    at Function.process_params (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:330:12)
    at next (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:271:10)
    at Function.handle (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:176:3)
    at EventEmitter.handle (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\application.js:173:10)
    at Server.app (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\express.js:38:9)
    at Server.emit (events.js:110:17)
    at HTTPParser.parserOnIncoming [as onIncoming] (_http_server.js:491:12)
    at HTTPParser.parserOnHeadersComplete (_http_common.js:111:23)
    at Socket.socketOnData (_http_server.js:343:22)
    at Socket.emit (events.js:107:17)
    at readableAddChunk (_stream_readable.js:163:16)
    at Socket.Readable.push (_stream_readable.js:126:10)

Support or instructions for webpack

I've been trying to get mock-fs working with webpack for a while. I'm not sure if mock-fs is not designed for a browser, but I'm trying to get webpack's dir-loader working with mocks.

It doesn't seem to be working and there are no instructions so I'm assuming this is not possible. Please let me know if there is support or plans for support for browser testing using mock-fs.

The use case is that I'm writing an electron app that works offline and uses js-git so I am hoping to use mock-fs to abstract out file operations and to speed up by development cycle since electron is quite slow to refresh and develop on.

Also, unless I'm missing something, it seems a little strange that a mocking library would depend on the original implementation.

access failing under 5.5.0

I feel like I must be doing something wrong, but I can't figure out what is happening here

I've golfed it down to this:

$ node -e 'require("mock-fs")({}); require("fs").access("foo",function(){});'
node_modules/mock-fs/node/fs-5.0.0.js:196
binding.access(pathModule._makeLong(path), mode, req);
^

TypeError: binding.access is not a function
at Object.fs.access (/home/dolszewski/mx/voice/dropcamel/node_modules/mock-fs/node/fs-5.0.0.js:196:11)
at [eval]:1:39
at Object.exports.runInThisContext (vm.js:54:17)
at Object. ([eval]-wrapper:6:22)
at Module._compile (module.js:413:34)
at node.js:611:27
at nextTickCallbackWith0Args (node.js:452:9)
at process._tickCallback (node.js:381:13)

any ideas?

Mock a call to return an error

I want to test that my code fails gracefully if there is an error reading or writing to the file system.

Do you have any recommendations on how to cause this to occur?

Add support for Node.js 6

When I run tests npm test, I get this error:

$ npm test

> [email protected] pretest /home/ppitonak/workspace/mock-fs
> eslint benchmarks lib test

> [email protected] test /home/ppitonak/workspace/mock-fs
> mocha --recursive test

/home/ppitonak/workspace/mock-fs/lib/index.js:36
  throw new Error('Unsupported Node version: ' + nodeVersion);
  ^

Error: Unsupported Node version: 6.0.0
    at Object.<anonymous> (/home/ppitonak/workspace/mock-fs/lib/index.js:36:9)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:456:32)
    at tryModuleLoad (module.js:415:12)
    at Function.Module._load (module.js:407:3)
    at Module.require (module.js:466:17)
    at require (internal/module.js:20:19)
    at Object.<anonymous> (/home/ppitonak/workspace/mock-fs/test/integration/filecount.spec.js:4:12)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:456:32)
    at tryModuleLoad (module.js:415:12)
    at Function.Module._load (module.js:407:3)
    at Module.require (module.js:466:17)
    at require (internal/module.js:20:19)
    at /home/ppitonak/workspace/mock-fs/node_modules/mocha/lib/mocha.js:219:27
    at Array.forEach (native)
    at Mocha.loadFiles (/home/ppitonak/workspace/mock-fs/node_modules/mocha/lib/mocha.js:216:14)
    at Mocha.run (/home/ppitonak/workspace/mock-fs/node_modules/mocha/lib/mocha.js:468:10)
    at Object.<anonymous> (/home/ppitonak/workspace/mock-fs/node_modules/mocha/bin/_mocha:403:18)
    at Module._compile (module.js:541:32)
    at Object.Module._extensions..js (module.js:550:10)
    at Module.load (module.js:456:32)
    at tryModuleLoad (module.js:415:12)
    at Function.Module._load (module.js:407:3)
    at Function.Module.runMain (module.js:575:10)
    at startup (node.js:159:18)
    at node.js:444:3
npm ERR! Test failed.  See above for more details.

Issues with buffers

Hey there,
first of all, thanks for the module, really enjoying it.

I have a module that does some piping (fetches files and directly saves them), however, when testing it, it fails with this error:

  1) downloading Nodes should download a specific version:
     Uncaught TypeError: binding.writeBuffers is not a function
      at writev (node_modules/mock-fs/node/fs-5.0.0.js:1962:11)
      at WriteStream._writev (node_modules/mock-fs/node/fs-5.0.0.js:1984:3)
      at doWrite (_stream_writable.js:290:12)
      at clearBuffer (_stream_writable.js:380:5)
      at onwrite (_stream_writable.js:331:7)
      at WritableState.onwrite (_stream_writable.js:89:5)
      at node_modules/mock-fs/node/fs-5.0.0.js:1946:5
      at wrapper (node_modules/mock-fs/node/fs-5.0.0.js:667:5)
      at node_modules/mock-fs/lib/binding.js:37:9

Could this be because the dependencies I used (got and tar.gz) are not compatible? The code, if needed, can be found here.

Thanks

[feature] control speed of writing/reading.

I still have to figure out how this would be exposed, but I need to test some case where there might be some concurrency between read and writes. Namely I have to test that locking mechanisms in place are efficient.

It would be useful to be able to mock a file's streaming speed.

File descriptor issues with Mocha in ElementaryOS

It seems mock-fs can't create the mock filesystem correctly in ElementaryOS??? This code works fine on OSX.

Mocha and Chai.expect are being used, here.

The test:

  /*
   * ::getFtpFileList
   */
  describe('::getFtpFileList', function () {
    var mockfs = require('mock-fs'),
        fs = require('fs');

    describe('When the directory contains only files', function () {
      before(function () {
        mockfs({
            'test': {
              'file.txt': 'contents',
              'file1.ext': ''
            }
        });
      });

      after(function () {
        mockfs.restore();
      });

      it('Injects a String Array of all the files with their full paths', function () {
        functions.getFtpFileList('test', function (err, files) {
          expect(files).to.deep.equal([
            'test/file.txt',
            'test/file1.ext'
          ]);

          expect(err).to.equal(null);
        });
      });
    });

The error

 6 passing (86ms)
  1 failing

  1) For module functions ::getFtpFileList When the directory contains only files "before all" hook:
     Uncaught Error: EBADF, bad file descriptor
    at Binding._getDescriptorById (/project_dir/node_modules/mock-fs/lib/binding.js:189:11)
    at Binding.<anonymous> (/project_dir/node_modules/mock-fs/lib/binding.js:375:27)
    at maybeCallback (/project_dir/node_modules/mock-fs/lib/binding.js:27:18)
    at Binding.writeBuffer (/project_dir/node_modules/mock-fs/lib/binding.js:374:10)
    at Object.fs.write (/project_dir/node_modules/mock-fs/node/fs-0.10.28.js:513:11)
    at WriteStream._write (/project_dir/node_modules/mock-fs/node/fs-0.10.28.js:1677:6)
    at doWrite (_stream_writable.js:226:10)
    at clearBuffer (_stream_writable.js:305:5)
    at onwrite (_stream_writable.js:263:7)
    at WritableState.onwrite (_stream_writable.js:97:5)
    at /project_dir/node_modules/mock-fs/node/fs-0.10.28.js:1683:5
    at Object.wrapper [as oncomplete] (/project_dir/node_modules/mock-fs/node/fs-0.10.28.js:510:5)

mock-fs does not work with babel

When using mock-fs 3.0.0 with babel, you get this error:

Message:
    /Users/matt/dev/get-nrdp/node_modules/mock-fs/node/fs-0.12.0.js:1
te = global.clearImmediate; var console = global.console; var __core-js_shared
                                                                    ^
Unexpected token -
Stack:
/Users/matt/dev/get-nrdp/node_modules/mock-fs/node/fs-0.12.0.js:1
te = global.clearImmediate; var console = global.console; var __core-js_shared
                                                                    ^
SyntaxError: Unexpected token -
    at exports.runInThisContext (vm.js:73:16)
    at Module._compile (module.js:443:25)
    at Module._extensions..js (module.js:478:10)
    at Object.require.extensions.(anonymous function) [as .js] (/Users/matt/dev/get-nrdp/node_modules/babel/node_modules/babel-core/lib/api/register/node.js:214:7)
    at Module.load (module.js:355:32)
    at Object.load (/Users/matt/dev/get-nrdp/node_modules/mock-fs/node_modules/rewire/lib/moduleEnv.js:19:18)
    at internalRewire (/Users/matt/dev/get-nrdp/node_modules/mock-fs/node_modules/rewire/lib/rewire.js:56:15)
    at rewire (/Users/matt/dev/get-nrdp/node_modules/mock-fs/node_modules/rewire/lib/index.js:11:12)
    at Object.<anonymous> (/Users/matt/dev/get-nrdp/node_modules/mock-fs/lib/index.js:42:14)
    at Module._compile (module.js:460:26)

This is because mock-fs is using rewire 2.0.0. rewire 2.0.0 did not correctly handle the global.__core-js_shared property, it tries to do var __core-js-shared = ...

rewire 2.3.0 addresses this issue. I forked mock-fs, upgraded to rewire 2.3.0 and now everything works great.

I'd send you a pull request, but I'm unsure if rewire 2.3.0 causes other issues.

Node v5.0.x support

/lib/index.js doesn't list Node v5 in its list of supported environments, so I can't use mock-fs based tests in the latest stable build of Node.

How to assert on created files?

My app creates files, and I want to do assertions against those created files. As far as I can tell, mock-fs is only allowing you to provide already existing mock files.

I do something like

mock({'fake/dir': {}});

myAppComponentCreateAFile('fake/dir/myfile.txt');

// this doesn't exist, wishful thinking
expect(mock.getFileContents('fake/dir/myfile.txt')).to.eql('contents of my created file');

I found if I have the main mock() return the FileSystem it creates, I can them do

var filesystem = mock({'fake/dir': {}});
myAppComponentCreateAFile('fake/dir/myfile.txt');
expect(filesystem.getItem('fake/dir/myfile.txt')._contents.toString()).to.eql('contents of my created file');

I just did this by adding return system at the bottom of mock(). Is there a better way that I missed?

Thanks for the useful module btw!

Does not support 2.0.0 version of io.js

It seems that support for the newest version of io.js needs to be added, as running mock against the latest version gives the error: Error: Unsupported Node version: 2.0.0

According to the 2.0 changelog it doesn't appear that there are any breaking changes.

`readdir` does not follow symlinks

fs = require('fs');
mockFs = require('mock-fs');
mockFs({
    '/fake': {
        'bar': {
            'hello.txt': 'Hello world'
        },
        'sym': mockFs.symlink({
            path: 'bar'
        })
    }
});

fs.readdir('/fake/bar', function(err, files) {
    console.log(err, files);
    fs.readdir('/fake/sym', function(err, files) {
        console.log(err, files);
    });
});

Expected output:

null [ 'hello.txt' ]
null [ 'hello.txt' ]

Actual output:

null [ 'hello.txt' ]
{ [Error: ENOTDIR, not a directory '/fake/sym']
  message: 'ENOTDIR, not a directory \'/fake/sym\'',
  code: 'ENOTDIR',
  errno: 27 } undefined

Doesn't work with node 4.2.1

I get the following error:

Error: Unsupported Node version: 4.2.1
    at Object.<anonymous> (/path/to/project/node_modules/mock-fs/lib/index.js:34:9)

access(Sync) doesn't play nice with fs-extra

Hello, lovely module you guys have here! I recently came across this bug with fs-extra and fs.access.

My quick test:

// File: test/mock.test.js
var mock = require('mock-fs');
var fs = require('fs-extra');

it("test1", function () {
  mock({
    dir: { file: "contents" }
  });
  fs.accessSync('dir', fs.F_OK);
})

Fails if you run mocha, but succeeds if you run mocha test/mock.test.js, but works fine if you use the fs module.

I'm on OSX 10.10.5, NodeJS 4.2.2, Mock-fs 3.7.0, fs-extra 0.26.5.

Can't require mock-fs in the Node REPL

$ node
> var MockFS = require('mock-fs');
TypeError: Object #<Object> has no method '__get__'
    at Object.<anonymous> (/home/rpaterson/Programming/signpost/core/node_modules/mock-fs/lib/index.js:29:30)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at repl:1:14
    at REPLServer.self.eval (repl.js:110:21)
    at repl.js:249:20

$ node --version
v0.10.30

Possible to mock __dirname?

Trying to mock path.resolve(__dirname + "../../../") because otherwise I get TypeError: Arguments to path.resolve must be strings. Is it possible with mock-fs?

Add support for node 4.x.x

Now that node 4.0.0 has been released as the stable version, it would be great to add support for this version.

Something is interfering on the tests

Hi everyone, I have this test case that works when I run just mocha tests but fail when I run on my default task with others tasks. Does anyone know what can be interfering on this? Any suggestion?

/*jshint expr: true*/
require('chai').should();
var proxyquire = require('proxyquire').noCallThru().noPreserveCache();
var sinon = require('sinon');
var mockFs = require('mock-fs');
var path = require('path');
var req = {};

describe.only('Components rendering', function(){

    beforeEach(function (done) {
        req = {
            project: {
                brand: 'bla',
                page: 'home',
                locale: 'en-gb',
                domain: 'bla.com'
            },
            query: {}
        };

        done();
    });

   afterEach(function (done){
        mockFs.restore();
        done();
    });

    it('should extend page config properly with component file', function (done) {

        var homeConfig = JSON.stringify({
            type: 'homepageLayout',
            slots: {
                'slot1': 'value1',
                '<<aComponent': {
                     file: 'theComponent.json'
                },
                '>>aSlot': {
                    file: 'header.json'
                }
            }
        });
        var componentJson = JSON.stringify({
            fooComponent: 'barComponent'
        });
        var headerJson = JSON.stringify({
            foo: 'bar'
        });

        var fsToMock = {};
        var pathFile = path.join(__dirname, '/../../../', process.env.PROJECT_ROOT, '/pageconfig/bla.com/en-gb/');
        var pathFile2 = path.join(__dirname, '/../../../', process.env.PROJECT_ROOT, '/pageconfig/project.com/en-gb/');

        fsToMock[path.join(pathFile + 'home.json')] = homeConfig;
        fsToMock[path.join(pathFile2 + 'home.json')] = homeConfig;

        fsToMock[path.join(pathFile + 'common/header.json')] = headerJson;
        fsToMock[path.join(pathFile + 'component/theComponent.json')] = componentJson;

        fsToMock[path.join(pathFile2 + 'common/header.json')] = headerJson;
        fsToMock[path.join(pathFile2 + 'component/theComponent.json')] = componentJson;

        var getConfig = require('../../../app/lib/page/getConfig');
        mockFs(fsToMock);

        getConfig(req, {}, function () {
            mockFs.restore();
            var expected = {
                slot1: 'value1',
                aComponent: {
                    fooComponent: 'barComponent'
                },
                aSlot: {
                    foo: 'bar'
                }
            };
            req.project.pageConfig.slots.should.deep.equal(expected);
            done();
        });

    });
});

The error is basically because it is not finding the file.

ENOENT, no such file or directory '/home/vagrant/project/app/pageconfig/project.com/en-gb/home.json'

and then

TypeError: Cannot read property 'slots' of undefined
      at /home/vagrant/project/test/server/lib/getConfigComponents.js:78:37
      at module.exports (/home/vagrant/project/app/lib/page/getConfig.js:69:20)
      at Context.<anonymous> (/home/vagrant/project/test/server/lib/getConfigComponents.js:67:9)
      at Test.Runnable.run (/home/vagrant/project/node_modules/grunt-mocha-test/node_modules/mocha/lib/runnable.js:204:15)
      at Runner.runTest (/home/vagrant/project/node_modules/grunt-mocha-test/node_modules/mocha/lib/runner.js:374:10)
      at /home/vagrant/project/node_modules/grunt-mocha-test/node_modules/mocha/lib/runner.js:452:12
      at next (/home/vagrant/project/node_modules/grunt-mocha-test/node_modules/mocha/lib/runner.js:299:14)
      at /home/vagrant/project/node_modules/grunt-mocha-test/node_modules/mocha/lib/runner.js:309:7
      at next (/home/vagrant/project/node_modules/grunt-mocha-test/node_modules/mocha/lib/runner.js:247:23)
      at /home/vagrant/project/node_modules/grunt-mocha-test/node_modules/mocha/lib/runner.js:271:7
      at done (/home/vagrant/project/node_modules/grunt-mocha-test/node_modules/mocha/lib/runnable.js:195:5)
      at /home/vagrant/project/node_modules/grunt-mocha-test/node_modules/mocha/lib/runnable.js:207:9
      at Context.<anonymous> (/home/vagrant/project/test/server/lib/getConfigComponents.js:22:9)
      at Hook.Runnable.run (/home/vagrant/project/node_modules/grunt-mocha-test/node_modules/mocha/lib/runnable.js:204:15)
      at next (/home/vagrant/project/node_modules/grunt-mocha-test/node_modules/mocha/lib/runner.js:259:10)
      at Object._onImmediate (/home/vagrant/project/node_modules/grunt-mocha-test/node_modules/mocha/lib/runner.js:276:5)

My default task which this test is failing is like this:

grunt.registerTask('default', [
        'clean:coverage',
        'lint',
        'compile-assets',
        'coverageandtest',
        'clienttest',
        'security'
    ]);

and the one I use and it pass is like this:

    grunt.registerTask('servertest', ['env:test', 'mochaTest:test', 'env:notTest']);

MockFS hides errors when used with Mocha and CoffeeScript

I'm using MockFS in my test suite with Mocha and Chai, but when a test fails and an error is thrown, the following error message is shown regardless of what the actual error is:

ENOENT, no such file or directory '/path/to/file/throwing/error.js'

This error is only thrown when another error occurs in the code, so it's not a disaster, but without the actual error message to look at it's obviously incredibly difficult to debug what's going on and fix my tests.

Any ideas on what could be causing this, or any chance of a fix?

This looks like a very similar issue to #14

Weird `require.extensions` after requiring mock-fs

Hi, thanks for this great library!

I run into a problem with mock-fs setting a weird { '.coffee': undefined } property on the global require.extensions object. This caused a problem when paired with node-dev. The problem I’ve described in the PR only appears when I require('mock-fs') in my tests.

I’ve fixed the interop on the node-dev side, so it’s not an urgent thing for me. But you might want to investigate this further.

Running with tests that don't use mockfs

I had some issues running unit tests (in mocha) with a mock-fs setup for a module that was also included in other tested modules, whose tests did not make use of mock-fs. This would only happen if the tests that did not use mock-fs ran first - so it seemed there was an issue with non-overridden modules being cached.

My solution was to add this to the top of test files that used mock-fs:

// Clear require cache to make sure mock-fs works
Object.keys(require.cache).forEach(function (key) {delete require.cache[key];}); 

I'm wondering if there's a better way to do this, or if it would be helpful to add this to the documentation?

fs.createReadStream test failures on Windows with Node 0.8

All tests pass with Node 0.10 and 0.11 on Windows, but with 0.8, I'm seeing a failure in the fs.createReadStream tests when piping to a write stream. No additional detail in the failure right now. I'm not currently set up to debug on Windows, but will try to dig a little.

What about events for fs actions?

Thanks for a great tool!

I'm stuck with a trouble of testing caching.
In my case I need to test of how many times file was read. But it's also could be useful to checking all actions on mocked fs.

p.s. For sure I can use sinon for that.

Default directory population

Hi @tschaub

Thanks for your awesome work on mock-fs.

I have used it to create a plugin for the unexpected assertion framework. It is still not ready for primetime, but I'm using it a few projects myself, and it's already proven really useful.

One of unexpected's greatest strengths are it's async assertions, which in combination with the plugin mentioned before, allows me to write assertions like this:

it('should read from the mock-fs', function () {
    return expect(function (cb) {
        fs.readFile('/data/foobar.txt', cb);
    }, 'with fs mocked out', {
        '/data': {
            'foobar.txt': 'Hello world',
        }
    }, 'to call the callback without error').then(function (fileContent) {
        return expect(fileContent, 'to equal', 'Hello world');
    });
});

I'm using mock-fs to create the filesystem and mountfs, to mount the filesystem on a path specified in the object given to the assertion.

The reason why it's preferable to me, to mount the mocks as subtrees of the filesystem instead of in the root is, that require uses fs to load modules. If I'm testing a module that does lazy loading of modules, it would not work, unless I also added those files to the file system.

Also, wrapping mock-fs into an assertion like this, makes it so that the life time of the mock is tightly coupled to the lifetime of the assertion.

My problem is, that mock-fs populates the mocked fs with some defualt folders.

// populate with default directories
var defaults = [os.tmpdir && os.tmpdir() || os.tmpDir(), process.cwd()];
defaults.forEach(function(dir) {
var parts = getPathParts(dir);
var directory = root;
var i, ii, name, candidate;
for (i = 0, ii = parts.length; i < ii; ++i) {
name = parts[i];
candidate = directory.getItem(name);
if (!candidate) {
directory = directory.addItem(name, new Directory());
} else if (candidate instanceof Directory) {
directory = candidate;
} else {
throw new Error('Failed to create directory: ' + dir);
}
}
});

I would like this to be configurable. If you do an fs.readdir on /data in the above example, you would not just get foobar.txt but also home and tmp (assuming that you are working on a linux machine and you run your tests from somewhere in the /home folder).

It is a very sensible default for all cases but this specific one where it's mounted on a real fs. :-)

mock-fs not compatible with graceful-fs >= 3.0.0

I am trying to use mock-fs to fake a file system and then perform reads using (a module that uses) graceful-fs.

Running this code:

var mock = require('mock-fs');
var graceful = require('graceful-fs');

mock({
  dir: {
    file1: 'contents of file1'
  }
});

var file1 = graceful.readFileSync('./dir/file1', {encoding: 'utf8'});

console.log(file1);

gives me

Error: ENOENT, no such file or directory './dir/file1'

Loading my package.json with this same code printed out fine. So looks like graceful-fs is reading from the real file system.

Based on the caveats section in the readme this should work. Am I doing something wrong here?

My versions are

node        0.10.36
graceful-fs 3.0.7
mock-fs     2.7.0

Back to back tests

I'm running two tests both with mock-fs running. I can run both tests individually just fine, however when I run the mocha command that runs both I get an error that one of my require's doesn't exist.

I tried running after with mock.restore() and it did nothing. Thoughts?

  after(function() {
    mock.restore()
  })

support for io.js v3.0.0

I'm seeing the following error when I try to run tests using io.js v3.0.0. I'm trying to upgrade from nodejs v0.10.38. Does mock-fs not support the latest io.js or is this error a red herring?

stream.js:74
      throw er; // Unhandled stream error in pipe.
      ^
Error: Unsupported Node version: 3.0.0
    at Object.<anonymous> (/Users/jfairley/Development/workspace-git/live-clipping/node_modules/mock-fs/lib/index.js:33:9)
    at Module._compile (module.js:430:26)
    at Object.Module._extensions..js (module.js:448:10)
    at Object.Module._extensions.(anonymous function) [as .js] (/Users/jfairley/Development/workspace-git/live-clipping/node_modules/gulp-istanbul/node_modules/istanbul/lib/hook.js:109:37)
    at Module.load (module.js:355:32)
    at Function.Module._load (module.js:310:12)
    at Function.Module._load (/Users/jfairley/Development/workspace-git/live-clipping/node_modules/mock-require/index.js:13:27)
    at Module.require (module.js:365:17)
    at require (module.js:384:17)
    at Object.<anonymous> (/Users/jfairley/Development/workspace-git/live-clipping/app/service/clipBusinessService_test.js:35:12)
npm ERR! Test failed.  See above for more details.
 ⇒ nvm current
iojs-v3.0.0

Mocking file system contents not working with gulp.src

http://stackoverflow.com/questions/30602416/mocking-file-system-contents-not-working-with-gulp-src

I'm trying to use mock-fs to mock up file system contents to test gulp tasks. Unfortunately, gulp.src doesn't seem to play well with mock-fs. Specifically, I get ENOENT errors:

Message:
    ENOENT, lstat '/vagrant/study-node-heroku/instances/development/app.json'
Details:
    errno: -2
    code: ENOENT
    path: /vagrant/study-node-heroku/instances/development/app.json
    domainEmitter: [object Object]
    domain: [object Object]
    domainThrown: false
Stack:
Error: ENOENT, lstat '/vagrant/study-node-heroku/instances/development/app.json'
    at Error (native)

Other parts of my code and test code access the mock-fs-created files just fine.

What am I doing wrong? I suspect that the problem is related to gulp's usage of vinyl.

Here is the function under test:

var herokuTarball = function(options, done) {
  var instance = options.instance || 'development';
  var tarballName = options.tarballName || instance
  var tarballPath = path.join(config.temp, tarballName + '.tar.gz');
  var files = path.join(config.instances, instance, '**/*');
  yassert.file(path.join(config.instances, instance, 'app.json'));

  async.waterfall([
    function(cb) {
      del([tarballPath], cb);
    },
    function(err, cb) {
      gulp.src(files)
        .pipe(tar(tarballName + '.tar'))
        .pipe(gzip())
        .pipe(gulp.dest(config.temp))
        .pipe(gcallback(cb));
    }
  ], function(err, result) {
    if (err) return err;
    return done(err, tarballPath);
  });
}

And here is the test snippet:

describe('gulp heroku:tarball', function() {
  after('something', function() {
    mock.restore();    
  });

  before('something', function() {
    mock({
      'instances/development': {
        'app.json': 'test content'
      }
    });
  });

  it('creates a tarball', function(done) {
    var options = {}

    heroku.herokuTarball(options, function(err, result) {
      expect(result).to.be.a('string');
      yassert.file(result);
      done();
    });
  });
});

Notice that the yassert (yeoman-assert) calls pass fine -- the file is there. If I take the function with the gulp.src call out of the async waterfall, the error goes away (and the test fails of course).

Using mock-fs to mock posting an image

I'm using mock-fs with supertest to test file uploads in an express application. I get hit with Error: ENOENT, no such file or directory messages from the endpoint, though in the context of the test the file is definitely present.

I've made a sample of my problem here: https://github.com/roc/mock-fs-supertest-express-example

Example response:

Error: ENOENT, no such file or directory 'public/images/c92a0180e347a9730417596326f3d166'
    at Binding.<anonymous> (mock-fs-supertest-express-example/node_modules/mock-fs/lib/binding.js:287:15)
    at maybeCallback (mock-fs-supertest-express-example/node_modules/mock-fs/lib/binding.js:27:18)
    at Binding.open (mock-fs-supertest-express-example/node_modules/mock-fs/lib/binding.js:274:10)
    at Object.fs.open (mock-fs-supertest-express-example/node_modules/mock-fs/node/fs-0.12.0.js:493:11)
    at WriteStream.open (mock-fs-supertest-express-example/node_modules/mock-fs/node/fs-0.12.0.js:1774:6)
    at new WriteStream (mock-fs-supertest-express-example/node_modules/mock-fs/node/fs-0.12.0.js:1764:10)
    at Object.fs.createWriteStream (mock-fs-supertest-express-example/node_modules/mock-fs/node/fs-0.12.0.js:1728:10)
    at mock-fs-supertest-express-example/node_modules/multer/storage/disk.js:38:26
    at Object.ondone (mock-fs-supertest-express-example/node_modules/multer/storage/disk.js:9:5)

I feel like I'm missing something fairly obvious (perhaps I just need to spy on the writing of the temporary file and return the same value?) though I'm unsure of the answer. Apologies if this turns out to not be directly to issues with mock-fs itself. I have working tests for actual files, but swapping out the large image file with a mocked file fails.

I will gladly contribute an idiots guide/express example PR if I can make sense of it, as I imagine this will be a fairly common use case for the library.

TypeError: Cannot set property '__set__' of undefined

Got the following error when mock-fs is loaded in a QUnit test on mac.

npm test

> test@ test /Users/jlu/projects/test
> qunit-cli tests/*.js

/Users/jlu/projects/test/node_modules/mock-fs/node/fs-0.12.0.js:1887
module.exports.__set__ = function __set__() {
                       ^
TypeError: Cannot set property '__set__' of undefined
    at Object.<anonymous> (/Users/jlu/projects/test/node_modules/mock-fs/node/fs-0.12.0.js:1887:24)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
    at Module.load (module.js:355:32)
    at Object.load (/Users/jlu/projects/test/node_modules/mock-fs/node_modules/rewire/lib/moduleEnv.js:19:18)
    at internalRewire (/Users/jlu/projects/test/node_modules/mock-fs/node_modules/rewire/lib/rewire.js:56:15)
    at rewire (/Users/jlu/projects/test/node_modules/mock-fs/node_modules/rewire/lib/index.js:11:12)
    at Object.<anonymous> (/Users/jlu/projects/test/node_modules/mock-fs/lib/index.js:42:14)
    at Module._compile (module.js:460:26)
    at Object.Module._extensions..js (module.js:478:10)
npm ERR! Test failed.  See above for more details.

Test:

var QUnit = require('qunit-cli');
var mock = require('mock-fs');

QUit.module('test');

test('test', function (assert){
  assert(strictEqual(1, 2));
})

Package.json

{
  "name": "test",
  "scripts": {
    "test": "node_modules/.bin/qunit-cli tests/*.js"
  },
  "devDependencies": {
    "mock-fs": "^3.0.0",
    "qunit-cli": "^0.2.0"
  }
}

mock uid and gid not working as expected

I'm writing a test suite to test my script that modify some directory. My test expecting failure if executed
without permission. Here, it mocks a directory to be owned by root. But, my script (which it task is move the directory) can still move that directory.

mockfs is broken since node 0.11.13

The problem is that process.binding('fs') does return an object that does not include Stats anymore.

The binding obj:

{ FSInitialize: [Function],
  close: [Function: close],
  open: [Function: open],
  read: [Function: read],
  fdatasync: [Function: fdatasync],
  fsync: [Function: fsync],
  rename: [Function: rename],
  ftruncate: [Function: ftruncate],
  rmdir: [Function: rmdir],
  mkdir: [Function: mkdir],
  readdir: [Function: readdir],
  stat: [Function: stat],
  lstat: [Function: lstat],
  fstat: [Function: fstat],
  link: [Function: link],
  symlink: [Function: symlink],
  readlink: [Function: readlink],
  unlink: [Function: unlink],
  writeBuffer: [Function: writeBuffer],
  writeString: [Function: writeString],
  chmod: [Function: chmod],
  fchmod: [Function: fchmod],
  chown: [Function: chown],
  fchown: [Function: fchown],
  utimes: [Function: utimes],
  futimes: [Function: futimes],
  StatWatcher: [Function: StatWatcher] }

The Error message:

TypeError: Cannot read property 'prototype' of undefined
    at Object.<anonymous> (/Users/mlegenhausen/dev/werk85/dk-navigator/server/node_modules/mock-fs/node/fs-0.11.10.js:122:9)

Error when reading a real file when mocking a file in the same directory

Consider the following

test.js

var mock = require('mock-fs');

mock({
  'index.js': 'module.exports = require("./sayHi");'
});

// Say hi
require('./index');

sayHi.js

console.log('Hi');

Running node test results in the following error.

module.js:340
    throw err;
          ^
Error: Cannot find module './sayHi'
    at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:280:25)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/Users/thomas/dev/test/index.js:1:80)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)

iojs and node 0.12 missing birth time on file stats

Node 0.11 introduced birthtime to represent the initial creation time of the file for supported systems, see:

https://nodejs.org/api/fs.html#fs_stat_time_values

Using mock-fs, issuing a stat results in no birthtime.

This isn't a huge issue as this property isn't well used so far, but through a complex set of interactions, causes unit tests to fail when cloning vinyl files as it uses the following logic to clone file stats:

https://github.com/hughsk/clone-stats/blob/master/index.js

I'm not sure if there are a couple of bugs here, when clone-stats created a new fs.Stats, shouldn't this stats object be intercepted by mock-fs? which would ensure all stats are normalized, either those created by fs.stat/fs.statSync or new fs.Stats.

Thanks,

Calls to asynchronous `fs.appendFile()` overwrite each other

Sequential calls to the asynchronous fs.appendFile() using this mocked library appear to conflict and overwrite each other, while the non-mocked library does not have this behavior.

Here is the behavior with the regular fs library:

var fs = require('fs');

var filename = './foo.txt';

for (var i = 0; i < 5; ++i) {
  fs.appendFile(filename, 'iteration' + i + '\n', function(error) {
    if (error) {
      console.log('Error:', error)
    }
    console.log('Added');
  });
}

setTimeout(function() {
  fs.readFile(filename, 'utf8', function (err, data) {
    if (err) throw err;
    console.log(data);
  });
}, 1000);

This outputs the following:

Added
Added
Added
Added
Added
iteration0
iteration4
iteration1
iteration3
iteration2

Note that this output is non-deterministic because the five writes could complete in any order. But that is tangential to this issue.

Now, using the mock-fs library:

var fs = require('fs');
var mockFs = require('mock-fs');

var filename = './foo.txt';

mockFs({
  '.': {}
});

for (var i = 0; i < 5; ++i) {
  fs.appendFile(filename, 'iteration' + i + '\n', function(error) {
    if (error) {
      console.log('Error:', error)
    }
    console.log('Added');
  });
}

setTimeout(function() {
  fs.readFile(filename, 'utf8', function (err, data) {
    if (err) throw err;
    console.log(data);
  });
}, 1000);

This outputs:

Added
Added
Added
Added
Added
iteration4

As you can see, only the last append succeeds. If we use the synchronous mocked version, all is well:

var fs = require('fs');
var mockFs = require('mock-fs');

var filename = './foo.txt';

mockFs({
  '.': {}
});

for (var i = 0; i < 5; ++i) {
  fs.appendFileSync(filename, 'iteration' + i + '\n');
}

setTimeout(function() {
  fs.readFile(filename, 'utf8', function (err, data) {
    if (err) throw err;
    console.log(data);
  });
}, 1000);

Outputs:

iteration0
iteration1
iteration2
iteration3
iteration4

I would like to use the asynchronous version of appendFile() because I don't care about the ordering of items, just that they all are there. I also don't want to block the process while the write is happening, which is what the synchronous version does.

Octal literals error

Node: 0.10.28

When using the following code:

mock({
  '../layers.json': ''
})

I'm getting the following error:

/Users/digitalsadhu/src/tfc-map/node_modules/mock-fs/lib/item.js:27
  this._mode = 0666;
               ^^^^
SyntaxError: Octal literals are not allowed in strict mode.

Implicit createCwd even with createCwd: false

While tinkering with mountfs and mock-fs combination, I discovered a weird behaviour of mock-fs.

Following code will create the process.cwd() even if not so desired by using the option.createCwd = false

let mockfs = ...
const dummyFS = {
  'foo': 'bar'
}

mockfs(dummyFS, {createCwd: false});

Currently my solution is using a root directory - but that's one extra indentation :/

let mockfs = ...
const dummyFS = {
 '/data': {
  'foo': 'bar'
 }  
}

mockfs(dummyFS, {createCwd: false});

This behavior seems counter intuitive, especially if you want to use the mockfs#fs functionality.

Issue Reading Directory Symlink.

The test below runs perfectly fine without mock and when the beforeEach and afterEach calls are added I get the corresponding errors below.

var path = require("path")
var chai = require("chai")
var expect = chai.expect

var mock = require("mock-fs")

var fs = require("fs")

describe("ensure-symlink", function(){
  beforeEach(function(){
    mock({
      "occupied-dir": {
        'foobar.txt': 'foobar\n',
      },
      'file.txt': 'file content\n',
      'empty-dir': {}
    })
  })
  afterEach(function() {
    mock.restore()
  })

  it("should create new directory symlink in root w/ resolve", function(){
    fs.symlinkSync(path.resolve("occupied-dir"), "empty-dir/symlink-dir", "dir")
    expect(fs.readdirSync("occupied-dir")).to.contain("foobar.txt")
    expect(fs.readdirSync("empty-dir")).to.contain("symlink-dir")
    expect(fs.lstatSync("empty-dir/symlink-dir").isSymbolicLink()).to.equal(true)
    expect(fs.readdirSync("empty-dir/symlink-dir")).to.contain("foobar.txt")
    expect(fs.readFileSync("empty-dir/symlink-dir/foobar.txt", "utf8")).to.equal("foobar\n")
  })
})

The line

expect(fs.readdirSync("empty-dir/symlink-dir")).to.contain("foobar.txt")

Throws Error: ENOTDIR, not a directory 'empty-dir/symlink-dir'

And the line

 expect(fs.readFileSync("empty-dir/symlink-dir/foobar.txt", "utf8")).to.equal("foobar\n")

Throws this:

TypeError: item.getItem is not a function
      at FileSystem.getItem (/Users/thomas/Desktop/untitled/node_modules/mock-fs/lib/filesystem.js:85:17)

So you can see the mock passes the first three expectations. It's just unable to open the directory and view the contents.

However without the mock, I can view the file and the contents of the symlink dir in finder and the test passes so also with node.js

What's happening here that's not allowing the mock to view the contents of the newly created symlink directory?

Require error with [email protected]

In [email protected] were changes with requirenodejs/node#1801

For real file system require works well, but with mock-fs fail with error.

How to reproduce:

var path = require('path'),
    fs = require('fs'),
    mock = require('mock-fs');

mock({
    'file.js': 'module.exports = 10;'
});

var filename = path.resolve('file.js'),
    contents = fs.readFileSync(filename, 'utf-8');

// File exists
console.log(contents); // module.exports = 10;

var val = require(filename); // throw error

console.log(val);

Expected:

module.exports = 10;
10

Actual:

module.js:334
    throw err;
          ^
Error: Cannot find module '/Users/blond/projects/mock-test/file.js'
    at Function.Module._resolveFilename (module.js:332:15)
    at Function.Module._load (module.js:282:25)
    at Module.require (module.js:361:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/Users/blond/projects/mock-test/index.js:14:11)
    at Module._compile (module.js:426:26)
    at Object.Module._extensions..js (module.js:444:10)
    at Module.load (module.js:351:32)
    at Function.Module._load (module.js:306:12)
    at Function.Module.runMain (module.js:467:10)

io.js support

I have not taken a deep look but it seems that this module does not work with io.js.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.