npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

unexpected-fs

v3.0.0

Published

mock-fs assertion for unexpected

Downloads

186

Readme

unexpected-fs

Mock filesystem for your assertions.

Unexpected file system :)

NPM version Build Status Coverage Status Dependency Status

Be aware that when you mock out the file system it will have side effects for the require function. require uses fs internally, and thus you will not be able to load modules from your local file system if you mount a mock-fs that shadows that location. This problem is mitigated by the fact that the mock file system will only exist while your assertion is running.

Usage

The unexpected-fs plugin adds the 'with fs mocked out' assertion to the assertion framework unexpected. You can mix it into any sequence of assertions, and it will patch the fs module for the assertions following it.

Take the following example:

var expect = require('unexpected');

var fs = require('fs');

function fileContentCAPS(filename) {
    var fileContent = fs.readFileSync('/data/' + filename, 'utf-8');
    return fileContent.toUpperCase();
}

expect('foobar.txt', 'when passed as parameter to', fileContentCAPS,
       'to equal', 'HELLO WORLD');

For that test to pass, you have to place fixtures on the file system. That poses two problems:

  • You remove data out of the context of the test.
  • Your tests become reliant on the file system.

In the following example, we mount a mocked fs on the path /data/ with a file named foobar.txt.

var expect = require('unexpected')
    .clone()
    .installPlugin(require('unexpected-fs');

var fs = require('fs');

function fileContentCAPS(filename) {
    var fileContent = fs.readFileSync('/data/' + filename, 'utf-8');
    return fileContent.toUpperCase();
}

expect('foobar.txt', 'with fs mocked out', {
    '/data': {
        'foobar.txt': 'Hello world',
    }
}, 'when passed as parameter to', fileContentCAPS, 'to equal', 'HELLO WORLD');

See the test suite in express-jsxtransform for a real life example of how it simplify your tests.

Assertions

with fs mocked out

Mocking out the filesystem for the rest of the rest of the duration of the given call to unexpected.

function fileContentCAPS(filename) {
    var fileContent = fs.readFileSync(filename, 'utf-8');
    return fileContent.toUpperCase();
}

expect('/data/foobar.txt', 'with fs mocked out', {
    '/data': {
        'foobar.txt': 'Hello world',
    }
}, 'when passed as parameter to', fileContentCAPS, 'to equal', 'HELLO WORLD');

to be a (path|text file) satisfying

Assert that the stats of a given path, or the stats, and the content, of a given path to a text file, satisfies the given object.

expect('/path/to/file', 'to be a text file satisfying', {
    ctime: new Date('Sun Jun 14 2015 23:40:01 GMT+0200'),
    content: 'the content as a utf-8 string'
});

The instance methods from fs.Stats, isFile, isDirectory, isSymbolicLink, isBlockDevice, isCharacterDevice, isFIFO and isSocket, is all made available as booleans on the stats object which is 'to satisfied' against.

expect('/path/to/directory', 'to be a path satisfying', {
    isDirectory: true,
    mode: 16877
});

<string> [not] to be an existing path

Asserts that the given string is a path that exists on the file system, or not.

expect('/path/that/does/not/exist', 'not to be an existing path');
expect('/', 'to be an existing path');

mock-fs and mountfs

This module is just a custom assertion that uses two other modules to mock out the filesystem for the duration of the expect call.

mock-fs is used to create the file system it self, and mountfs to mount those filesystems on top of the real filesystem.

mountfs is used to avoid altering more than necessary. If you only used mock-fs, you would change fs entirely for the entire process, which would mean that you could not test code that relied on lazy loading of modules through require for example.

How mock-fs is used

To make mock-fs work for us in this context I had to depart from their API on a few ways:

The mock.file() helper method would not be available as the user should not be required to do more than just install the unexpected-fs plugin. Using mock fs you would call with an options object, like so:

mock.file({
    ctime: new Date(112432332),
    content: 'foobar'
});

You can do the same with unexpected-fs, by just passing the options object but adding a property called _isFile with the value of true.

{
    _isFile: true,
    ctime: new Date(112432332),
    content: 'foobar'
}

Before passing the arguments on to mock-fs, the _isFile property will be removed and the object will be passed to mock.file.

The same is true for the mock.directory and mock.symlink methods, and the corresponding properties is called _isDirectory and _isSymlink.

Another difference is a consequence of how mountfs is added to the mix. mock-fs would normally overwrite the entire global fs module, and you would not be able to read from the already existing file system. That is solved by only mocking out part of the file system, as given by the mountPath. Say that we want to mock out a file called journal.txt in the folder /home/john/notes.

it('should be able to read the contents of a file', function () {
    return expect(function () {
        var fs = require('fs');
        var fileContent = fs.readFileSync('/home/john/notes/journal.txt', 'utf-8');
        return expect(fileContent, 'to equal', 'foo bar');
    }, 'with fs mocked out', {
        '/home/john/notes': {
            'journal.txt': 'foo bar'
        }
    }, 'not to throw');
});

If the original file system had data in /home/john/notes/ those data will now be hidden by our mock fs. If the folders /home, or /home/john, or /home/john/notes did not exist on the original file system, they will appear to do now.

You are not able to mock out files, without mounting a mock-fs first. So the following example will NOT work:

expect(..., 'with fs mocked out', {
    '/path/to/file.txt': 'blah'
}, ...);

While it could be convenient to do it like the above example, it is a tradeoff which enables us to mount multiple small mocked file systems instead of having to override everything at once. Each key, on the root level of the configuration object will be it's own little mock fs. Consider this example:

expect(..., 'with fs mocked out', {
    '/home/john/notes': { ... },
    '/home/john/documents': { ... }
}, ...);

That allows us to mock out both folders mentioned in the object, while still being able to read stuff in the folders outside of the mounted mock file systems.

License

This module is made public under the ISC License.

See the LICENSE file for additional details.