UNPKG

enb

Version:

Faster BEM/BEViS assembler

441 lines (410 loc) 15.8 kB
var fs = require('fs'); var inherit = require('inherit'); var vow = require('vow'); var path = require('path'); var asyncFs = require('../../fs/async-fs'); /** * @name TestFileSystem */ module.exports = inherit({ __constructor: function (fileSystemStructure, root) { this._structure = fileSystemStructure; this._root = root || process.cwd(); this._originalFsFunctions = null; this._originalAsyncFsFunctions = null; }, setup: function () { var mocks = createMocks(this._structure, this._root); this._originalAsyncFsFunctions = {}; for (var asyncFsMethodName in asyncFs) { this._originalAsyncFsFunctions[asyncFsMethodName] = asyncFs[asyncFsMethodName]; // Заменяем пустой функцией для безопасности. asyncFs[asyncFsMethodName] = createEmptyFunction(asyncFsMethodName); } for (var asyncFsMockName in mocks.vowFs) { asyncFs[asyncFsMockName] = mocks.vowFs[asyncFsMockName]; } this._originalFsFunctions = {}; for (var fsMethodName in fs) { this._originalFsFunctions[fsMethodName] = fs[fsMethodName]; // Заменяем пустой функцией для безопасности. fs[fsMethodName] = createEmptyFunction(fsMethodName); } for (var fsMockName in mocks.fs) { fs[fsMockName] = mocks.fs[fsMockName]; } }, teardown: function () { for (var asyncFsMethodName in this._originalAsyncFsFunctions) { asyncFs[asyncFsMethodName] = this._originalAsyncFsFunctions[asyncFsMethodName]; } for (var fsMethodName in this._originalFsFunctions) { fs[fsMethodName] = this._originalFsFunctions[fsMethodName]; } } }); function createEmptyFunction(methodName) { return function () { throw new Error('Mock `' + methodName + '` is not implemented.'); }; } function createMocks (structure, root) { var timeObj = new Date(); function isAbsolutePath(filePath) { return filePath === path.resolve(filePath); } function getRelativePath(filePath) { if (isAbsolutePath(filePath)) { if (filePath.indexOf(root + path.sep) === 0) { return filePath.replace(root + path.sep, ''); } else { return null; } } else { return filePath; } } function getNodeName(node) { if (node.directory) { return node.directory; } else { return node.file; } } function getNode(filePath) { filePath = getRelativePath(filePath); var pathBits = filePath.split(path.sep); var nodeItems = structure; var currentPathBit; var foundNode; while (Boolean(currentPathBit = pathBits.shift())) { if (!nodeItems) { return null; } foundNode = null; for (var i = 0; i < nodeItems.length; i++) { var subNode = nodeItems[i]; if (getNodeName(subNode) === currentPathBit) { foundNode = subNode; } } if (!foundNode) { return null; } nodeItems = foundNode.items; } return foundNode; } function isFile(node) { return !!node.file; } function isDirectory(node) { return !!node.directory; } function isSocket() { return false; } function isSymLink() { return false; } function createFileNotFoundError(filename) { return new Error('File not found: ' + filename + ' (' + getRelativePath(filename) + ')'); } function createIsDirectoryError(filename) { return new Error('Path is a directory: ' + filename); } function createIsFileError(filename) { return new Error('Path is a file: ' + filename); } function createFileNode(name, content) { return {file: name, content: content}; } function createDirectoryNode(name) { return {directory: name, items: []}; } function createStats(node) { return { uid: 0, gid: 0, isFile: function () { return isFile(node); }, isDirectory: function () { return isDirectory(node); }, isSymbolicLink: function () { return isSymLink(node); }, isSocket: function () { return isSocket(node); }, size: node.content ? node.content.length : 0, atime: timeObj, mtime: timeObj, ctime: timeObj }; } return { vowFs: { read: function (filename) { try { return vow.fulfill(this._readSync(filename)); } catch (e) { return vow.reject(e); } }, _readSync: function (filename) { var node = getNode(filename); if (node) { if (isFile(node)) { return node.content; } else { throw createIsDirectoryError(filename); } } else { throw createFileNotFoundError(filename); } }, write: function (filename, content) { var node = getNode(filename); if (node) { if (isFile(node)) { node.content = content; return vow.resolve(); } else { return vow.reject(createIsDirectoryError(filename)); } } else { var parentNode = getNode(path.dirname(filename)); if (parentNode) { if (isDirectory(parentNode)) { parentNode.items.push(createFileNode(path.basename(filename), content)); return vow.resolve(); } else { return vow.reject(createIsFileError(filename)); } } else { return vow.reject(createFileNotFoundError(filename)); } } }, append: function (filename, data) { return this.read(filename, function (content) { return this.write(filename, content + data); }.bind(this)); }, remove: function (filename) { var node = getNode(filename); if (node) { if (isFile(node)) { var parentNode = getNode(path.basename(filename)); parentNode.items.splice(parentNode.items.indexOf(node), 1); return vow.fulfill(); } else { return vow.reject(createIsDirectoryError(filename)); } } else { return vow.reject(createFileNotFoundError(filename)); } }, removeDir: function (dirPath) { var node = getNode(dirPath); if (node) { if (isDirectory(node)) { var parentNode = getNode(path.basename(dirPath)); parentNode.items.splice(parentNode.items.indexOf(node), 1); return vow.fulfill(); } else { return vow.reject(createIsFileError(dirPath)); } } else { return vow.reject(createFileNotFoundError(dirPath)); } }, move: function (source, dest) { return this.copy(source, dest).then(function () { return this.isFile(source).then(function (isFile) { return isFile ? this.remove(source) : this.removeDir(source); }.bind(this)); }.bind(this)); }, copy: function (source, dest) { var node = getNode(source); var destNode = getNode(dest); if (destNode) { var destParentNode = getNode(path.basename(dest)); destParentNode.items.splice(destParentNode.items.indexOf(destNode), 1); } if (node) { if (isFile(node)) { return this.read(source).then(function (data) { return this.write(dest, data); }.bind(this)); } else { return this.makeDir(dest).then(function () { return this.listDir(source).then(function (filenames) { return vow.all(filenames.map(function (filename) { return this.copy(path.join(source, filename), path.join(dest, filename)); }, this)); }.bind(this)); }.bind(this)); } } else { throw createFileNotFoundError(source); } }, listDir: function (dirPath) { var node = getNode(dirPath); if (node) { if (isDirectory(node)) { return vow.fulfill(node.items.map(function (subNode) { return getNodeName(subNode); })); } else { return vow.reject(createIsFileError(dirPath)); } } else { return vow.reject(createFileNotFoundError(dirPath)); } }, makeDir: function (dirPath) { var node = getNode(dirPath); if (node) { if (isFile(node)) { return vow.reject(createIsFileError(dirPath)); } else { return vow.fulfill(); } } else { var parentDirPath = path.basename(dirPath); return this.makeDir(parentDirPath).then(function () { var parentNode = getNode(parentDirPath); var childNode = getNode(dirPath); if (childNode && parentNode.items.indexOf(childNode) !== -1) { if (isDirectory(childNode)) { return vow.fulfill(); } else { return vow.reject(createIsFileError(dirPath)); } } else { parentNode.items.push(createDirectoryNode(path.basename(dirPath))); return vow.fulfill(); } }); } }, isFile: function (filename) { var node = getNode(filename); if (node) { return vow.fulfill(isFile(node)); } else { return vow.reject(createFileNotFoundError(filename)); } }, isDir: function (filename) { var node = getNode(filename); if (node) { return vow.fulfill(isDirectory(node)); } else { return vow.reject(createFileNotFoundError(filename)); } }, isSocket: function (filename) { var node = getNode(filename); if (node) { return vow.fulfill(isSocket(node)); } else { return vow.reject(createFileNotFoundError(filename)); } }, isSymLink: function (filename) { var node = getNode(filename); if (node) { return vow.fulfill(isSymLink(node)); } else { return vow.reject(createFileNotFoundError(filename)); } }, exists: function (filename) { return vow.fulfill(Boolean(getNode(filename))); }, absolute: function (filename) { return vow.fulfill(path.resolve(root, filename)); }, chown: function () { return vow.fulfill(); // не поддерживаем права }, chmod: function () { return vow.fulfill(); // не поддерживаем права }, stats: function (filename) { var node = getNode(filename); if (node) { return vow.fulfill(createStats(node)); } else { return vow.reject(createFileNotFoundError(filename)); } }, link: function () { return vow.fulfill(); // не поддерживаем ссылки }, symLink: function () { return vow.fulfill(); // не поддерживаем ссылки } }, fs: { existsSync: function (filename) { return Boolean(getNode(filename)); }, statSync: function (filename) { var node = getNode(filename); if (node) { return createStats(node); } else { throw createFileNotFoundError(filename); } }, readdir: function (dirPath, callback) { var node = getNode(dirPath); if (!node) { return callback(createFileNotFoundError(dirPath)); } if (!isDirectory(node)) { return callback(createIsFileError(dirPath)); } callback(undefined, node.items.map(function (subNode) { return getNodeName(subNode); })); }, readdirSync: function (dirPath) { var node = getNode(dirPath); if (node) { if (isDirectory(node)) { return node.items.map(function (subNode) { return getNodeName(subNode); }); } else { throw createIsFileError(dirPath); } } else { throw createFileNotFoundError(dirPath); } }, realpathSync: function (destPath) { return path.resolve(process.cwd(), destPath); }, readFileSync: function (filename) { var node = getNode(filename); if (node) { if (isFile(node)) { return node.content; } else { throw createIsDirectoryError(filename); } } else { throw createFileNotFoundError(filename); } } } }; }