Skip to content

Commit

Permalink
FileSystem tests.
Browse files Browse the repository at this point in the history
  • Loading branch information
billmalarky committed Nov 2, 2017
1 parent b89ad7b commit f1ba98b
Show file tree
Hide file tree
Showing 2 changed files with 219 additions and 7 deletions.
173 changes: 171 additions & 2 deletions tests/FileSystem.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,85 @@

// Load dependencies
import should from 'should'; // eslint-disable-line no-unused-vars
import FileSystemFactory from '../lib/FileSystem';
import FileSystemFactory, { FileSystem } from '../lib/FileSystem';
import pathLib from 'path';

describe('lib/FileSystem', function() {

const fileSystem = FileSystemFactory();
// Test static class properties and methods
it('FileSystem class cache locking logic should work as expected.', () => {

// Cache lock should default to empty
FileSystem.cacheLock.should.deepEqual({});

// Adding files to cache lock should work as expected.
FileSystem.lockCacheFile('test-file-name.jpg', 'arbitrary-uuid-1');
FileSystem.lockCacheFile('test-file-name.jpg', 'arbitrary-uuid-2');
FileSystem.cacheLock.should.deepEqual({
'test-file-name.jpg': {
'arbitrary-uuid-1': true,
'arbitrary-uuid-2': true
}
});

// Unlocking cache files should work as expected.
FileSystem.unlockCacheFile('test-file-name.jpg', 'arbitrary-uuid-1');
FileSystem.unlockCacheFile('test-file-name.jpg', 'arbitrary-uuid-2');
FileSystem.cacheLock.should.deepEqual({});

});

it('#constructor should initialize object properties correctly.', () => {

const fileSystem = FileSystemFactory();

fileSystem.should.have.properties({
os: 'ios',
cachePruneTriggerLimit: 15728640,
baseFilePath: '/ios-test/react-native-image-cache-hoc/'
});

});

it('#_setBaseFilePath should set a base filepath correctly.', () => {

const fileSystem = FileSystemFactory();

fileSystem._setBaseFilePath('test-file-dir-name').should.equal('/ios-test/test-file-dir-name/');

});

it('#_validatePath should validate the file path is safe.', () => {

const fileSystem = FileSystemFactory();

let badPath = '../../../../badpath';

try {
fileSystem._validatePath(badPath)
} catch (error) {
let resolvedPath = pathLib.resolve('/ios-test/react-native-image-cache-hoc/' + badPath);
error.should.deepEqual(new Error(resolvedPath + ' is not a valid file path.'));
}

let goodPath = 'safe/path';

fileSystem._validatePath(goodPath).should.be.true();

});

it('#exists mocked as true.', () => {

const fileSystem = FileSystemFactory();

fileSystem.exists('abitrary-file.jpg').should.be.true();

});

it('#getFileNameFromUrl should create a sha1 filename from a PNG/JPG/GIF url.', () => {

const fileSystem = FileSystemFactory();

let pngFilename = fileSystem.getFileNameFromUrl('https://img.wennermedia.com/5333a62d-07db-432a-92e2-198cafa38a14-326adb1a-d8ed-4a5d-b37e-5c88883e1989.png');

pngFilename.should.equal('cd7d2199cd8e088cdfd9c99fc6359666adc36289.png');
Expand All @@ -26,4 +97,102 @@ describe('lib/FileSystem', function() {

});

it('#fetchFile should validate path.', () => {

const fileSystem = FileSystemFactory();

let badFileName = '../../../../bad-filename.jpg';

return fileSystem.fetchFile('https://google.com/arbitrary.jpg', true, badFileName)
.then(() => {
throw new error('Bad file name was not caught.');
})
.catch((error) => {
let resolvedPath = pathLib.resolve('/ios-test/react-native-image-cache-hoc/' + badFileName);
error.should.deepEqual(new Error(resolvedPath + ' is not a valid file path.'));
});

});

it('#fetchFile clobber safeguard should work.', () => {

const fileSystem = FileSystemFactory();

// fileSystem.exists() is mocked to always return true, so error should always be thrown unless clobber is set to true.
return fileSystem.fetchFile('https://img.wennermedia.com/5333a62d-07db-432a-92e2-198cafa38a14-326adb1a-d8ed-4a5d-b37e-5c88883e1989.png')
.then(() => {
throw new error('Clobber logic failed, a file was overwritten.');
})
.catch((error) => {
error.should.deepEqual(new Error('A file already exists at /ios-test/react-native-image-cache-hoc/cache/cd7d2199cd8e088cdfd9c99fc6359666adc36289.png and clobber is set to false.'));
});

});

it('#fetchFile prune logic should not be called on permanent writes.', () => {

const fileSystem = FileSystemFactory();

let pruneCacheHit = false;

// Mock fileSystem.pruneCache() to determine if it is called correctly.
fileSystem.pruneCache = () => {
pruneCacheHit = true;
};

// fileSystem.exists() is mocked to always return true, so error should always be thrown unless clobber is set to true.
return fileSystem.fetchFile('https://img.wennermedia.com/5333a62d-07db-432a-92e2-198cafa38a14-326adb1a-d8ed-4a5d-b37e-5c88883e1989.png', true, null, true)
.then(() => {
pruneCacheHit.should.be.false();
});

});

it('#fetchFile prune logic should be called on cache writes.', () => {

const fileSystem = FileSystemFactory();

let pruneCacheHit = false;

// Mock fileSystem.pruneCache() to determine if it is called correctly.
fileSystem.pruneCache = () => {
pruneCacheHit = true;
};

// fileSystem.exists() is mocked to always return true, so error should always be thrown unless clobber is set to true.
return fileSystem.fetchFile('https://img.wennermedia.com/5333a62d-07db-432a-92e2-198cafa38a14-326adb1a-d8ed-4a5d-b37e-5c88883e1989.png', false, null, true)
.then(() => {
pruneCacheHit.should.be.true();
});

});

it('#fetchFile should work as expected.', () => {

const fileSystem = FileSystemFactory();

// Mock fileSystem.pruneCache().
fileSystem.pruneCache = () => {};

// fileSystem.exists() is mocked to always return true, so error should always be thrown unless clobber is set to true.
return fileSystem.fetchFile('https://img.wennermedia.com/5333a62d-07db-432a-92e2-198cafa38a14-326adb1a-d8ed-4a5d-b37e-5c88883e1989.png', false, null, true)
.then((result) => {

result.should.deepEqual({
path: '/this/is/path/to/file.jpg',
fileName: 'cd7d2199cd8e088cdfd9c99fc6359666adc36289.png'
});

});

});

it('#pruneCache should not throw errors.', () => {

const fileSystem = FileSystemFactory();

return fileSystem.pruneCache();

});

});
53 changes: 48 additions & 5 deletions tests/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,57 @@

/* global jest */

/**
* Override native modules with mocks where necessary.
*/
jest.mock('react-native', () => {

let ReactNative = require.requireActual('react-native');

ReactNative.Platform.OS = 'ios';

return ReactNative;

});

jest.mock('react-native-fetch-blob', () => {
return {

// Define mock object before returning so it can reference itself to resolve method chains.
let mockRNFetchBlob = {
fs: {
dirs: {
CacheDir: 'test'
CacheDir: '/ios-test',
DocumentDir: '/android-test'
},
exists: () => { return true },
lstat: () => {

let lstat = [
{"size":"43663","path":"/ios-test/cache/0fbbfec764c73ee5b4e3a0cb8861469bc9fc6c8c.jpg","filename":"0fbbfec764c73ee5b4e3a0cb8861469bc9fc6c8c.jpg","lastModified":1508878829000,"type":"file"},
{"size":"88937","path":"/ios-test/cache/6865fd0a65771b0044319f562873cc7b145abb4a.jpg","filename":"6865fd0a65771b0044319f562873cc7b145abb4a.jpg","lastModified":1508877930000,"type":"file"},
{"size":"14133330","path":"/ios-test/cache/b003269c377af6a2f53f59bc127a06c86f54312b.jpg","filename":"b003269c377af6a2f53f59bc127a06c86f54312b.jpg","lastModified":1508877698000,"type":"file"},
{"size":"1684","path":"/ios-test/cache/d1052b9f22c1f00f4d658224f4295307b97db69f.jpg","filename":"d1052b9f22c1f00f4d658224f4295307b97db69f.jpg","lastModified":1508877954000,"type":"file"},
{"size":"65769","path":"/ios-test/cache/faf4e58257d988ea6eab23aee5e5733bff9b2a9e.jpg","filename":"faf4e58257d988ea6eab23aee5e5733bff9b2a9e.jpg","lastModified":1509634852000,"type":"file"}
];

return lstat;

}
},
DocumentDir: () => {},
polyfill: () => {},
}
};

mockRNFetchBlob.config = () => {
return mockRNFetchBlob; // Must return reference to self to support method chaining.
};

mockRNFetchBlob.fetch = () => {
return {
path: () => {
return '/this/is/path/to/file.jpg'
}
};
};

return mockRNFetchBlob;

});

0 comments on commit f1ba98b

Please sign in to comment.