[Pkg-javascript-commits] [node-fined] 01/04: Import Upstream version 1.0.2

Paolo Greppi paolog-guest at moszumanska.debian.org
Tue Dec 13 16:40:47 UTC 2016


This is an automated email from the git hooks/post-receive script.

paolog-guest pushed a commit to branch master
in repository node-fined.

commit aa58ec1ef89e587d36f9131dffbe92648ebf1960
Author: Paolo Greppi <paolo.greppi at libpf.com>
Date:   Mon Dec 12 13:04:08 2016 +0000

    Import Upstream version 1.0.2
---
 .editorconfig                    |   12 +
 .eslintrc                        |    3 +
 .gitignore                       |   30 +
 .jscsrc                          |    4 +
 .travis.yml                      |   10 +
 LICENSE                          |   21 +
 README.md                        |   67 ++
 appveyor.yml                     |   25 +
 index.js                         |  159 ++++
 package.json                     |   47 ++
 test/fixtures/fined/app.js       |    0
 test/fixtures/fined/appfile.js   |    0
 test/fixtures/fined/appfile.json |    0
 test/fixtures/fined/index.json   |    0
 test/fixtures/fined/package.json |    2 +
 test/index.js                    | 1693 ++++++++++++++++++++++++++++++++++++++
 test/utils/create-symlinks.js    |   33 +
 test/utils/get-userhome-file.js  |   25 +
 18 files changed, 2131 insertions(+)

diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..5760be5
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,12 @@
+# http://editorconfig.org
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+[*.md]
+trim_trailing_whitespace = false
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..a5a4a17
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,3 @@
+{
+  "extends": "gulp"
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1381c79
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,30 @@
+# Logs
+logs
+*.log
+
+# Runtime data
+pids
+*.pid
+*.seed
+
+# Directory for instrumented libs generated by jscoverage/JSCover
+lib-cov
+
+# Coverage directory used by tools like istanbul
+coverage
+
+# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
+.grunt
+
+# node-waf configuration
+.lock-wscript
+
+# Compiled binary addons (http://nodejs.org/api/addons.html)
+build/Release
+
+# Dependency directory
+# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
+node_modules
+
+.DS_Store
+test/fixtures/fined/symlink*
diff --git a/.jscsrc b/.jscsrc
new file mode 100644
index 0000000..fe2d43a
--- /dev/null
+++ b/.jscsrc
@@ -0,0 +1,4 @@
+{
+  "preset": "gulp",
+  "excludeFiles": ["test/fixtures/fined/symlink*"]
+}
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..0d50ecf
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,10 @@
+sudo: false
+language: node_js
+node_js:
+  - '6'
+  - '5'
+  - '4'
+  - '0.12'
+  - '0.10'
+after_script:
+  - npm run coveralls
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..3ca2d3f
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2016 Blaine Bublitz, Tyler Kellen and other contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8788de0
--- /dev/null
+++ b/README.md
@@ -0,0 +1,67 @@
+# Fined [![Build Status][travis-image]][travis-url] [![Build Status][appveyor-image]][appveyor-url]
+
+> Find a file given a declaration of locations
+
+[![NPM](https://nodei.co/npm/fined.png)](https://nodei.co/npm/fined/)
+
+## Usage
+
+```js
+var fined = require('fined');
+
+fined({ path: 'path/to/file', extensions: ['.js', '.json'] });
+// => { path: '/absolute/path/to/file.js', extension: '.js' }  (if file exists)
+// => null  (if file does not exist)
+
+var opts = {
+  name: '.app',
+  cwd: '.',
+  extensions: {
+    'rc': 'default-rc-loader', 
+    '.yml': 'default-yml-loader',
+  },
+};
+
+fined({ path: '.' }, opts);
+// => { path: '/absolute/of/cwd/.app.yml', extension: { '.yml': 'default-yml-loader' } }
+
+fined({ path: '~', extensions: { 'rc': 'some-special-rc-loader' } }, opts);
+// => { path: '/User/home/.apprc', extension: { 'rc': 'some-special-rc-loader' } }
+```
+
+## API
+
+### fined(pathObj, opts) => object | null
+
+#### Arguments:
+
+* **pathObj** [string | object] : a path setting for finding a file.
+* **opts** [object] : a plain object supplements `pathObj`.
+
+   `pathObj` and `opts` can have same properties:
+
+   * **path** [string] : a path string.
+   * **name** [string] : a basename.
+   * **extensions**: [string | array | object] : extensions.
+   * **cwd**: a base directory of `path` and for finding up.
+   * **findUp**: [boolean] : a flag to find up.
+
+#### Return:
+
+This function returns a plain object which consists of following properties if a file exists otherwise null.
+
+   * **path** : an absolute path
+   * **extension** : a string or a plain object of extension.
+
+
+## License
+
+MIT
+
+
+[npm-image]: http://img.shields.io/badge/npm-v0.0.0-blue.svg
+[npm-url]: https://www.npmjs.org/package/fined
+[travis-image]: https://travis-ci.org/js-cli/fined.svg?branch=master
+[travis-url]: https://travis-ci.org/js-cli/fined
+[appveyor-image]: https://ci.appveyor.com/api/projects/status/github/js-cli/fined?branch=master&svg=true
+[appveyor-url]: https://ci.appveyor.com/project/js-cli/fined
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..625fc10
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,25 @@
+# http://www.appveyor.com/docs/appveyor-yml
+# http://www.appveyor.com/docs/lang/nodejs-iojs
+
+environment:
+  matrix:
+    # node.js
+    - nodejs_version: "0.10"
+    - nodejs_version: "0.12"
+    - nodejs_version: "4"
+    - nodejs_version: "5"
+    - nodejs_version: "6"
+
+install:
+  - ps: Install-Product node $env:nodejs_version
+  - npm install
+
+test_script:
+  - node --version
+  - npm --version
+  - cmd: npm test
+
+build: off
+
+# build version format
+version: "{build}"
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..fed7aae
--- /dev/null
+++ b/index.js
@@ -0,0 +1,159 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+var isString = require('lodash.isstring');
+var isPlainObject = require('lodash.isplainobject');
+var isEmpty = require('lodash.isempty');
+var pick = require('lodash.pick');
+var assignWith = require('lodash.assignwith');
+
+var expandTilde = require('expand-tilde');
+var parsePath = require('parse-filepath');
+
+function assignNullish(objValue, srcValue) {
+  return (srcValue == null ? objValue : srcValue);
+}
+
+function defaults(mainObj, defaultObj) {
+  return assignWith({}, defaultObj, mainObj, assignNullish);
+}
+
+function fined(pathObj, defaultObj) {
+  var expandedPath = expandPath(pathObj, defaultObj);
+  return expandedPath ? findWithExpandedPath(expandedPath) : null;
+}
+
+function expandPath(pathObj, defaultObj) {
+  if (!isPlainObject(defaultObj)) {
+    defaultObj = {};
+  }
+
+  if (isString(pathObj)) {
+    pathObj = { path: pathObj };
+  }
+
+  if (!isPlainObject(pathObj)) {
+    pathObj = {};
+  }
+
+  pathObj = defaults(pathObj, defaultObj);
+
+  var filePath;
+  if (!isString(pathObj.path)) {
+    return null;
+  }
+  // Execution of toString is for a String object.
+  if (isString(pathObj.name) && pathObj.name) {
+    if (pathObj.path) {
+      filePath = expandTilde(pathObj.path.toString());
+      filePath = path.join(filePath, pathObj.name.toString());
+    } else {
+      filePath = pathObj.name.toString();
+    }
+  } else {
+    filePath = expandTilde(pathObj.path.toString());
+  }
+
+  var extArr = createExtensionArray(pathObj.extensions);
+  var extMap = createExtensionMap(pathObj.extensions);
+
+  var basedir = isString(pathObj.cwd) ? pathObj.cwd.toString() : '.';
+  basedir = path.resolve(expandTilde(basedir));
+
+  var findUp = !!pathObj.findUp;
+
+  var parsed = parsePath(filePath);
+  if (parsed.isAbsolute) {
+    filePath = filePath.slice(parsed.root.length);
+    findUp = false;
+    basedir = parsed.root;
+  } else if (parsed.root) { // Expanded path has a drive letter on Windows.
+    filePath = filePath.slice(parsed.root.length);
+    basedir = path.resolve(parsed.root);
+  }
+
+  return {
+    path: filePath,
+    basedir: basedir,
+    findUp: findUp,
+    extArr: extArr,
+    extMap: extMap,
+  };
+}
+
+function findWithExpandedPath(expanded) {
+  var found = expanded.findUp ?
+    findUpFile(expanded.basedir, expanded.path, expanded.extArr) :
+    findFile(expanded.basedir, expanded.path, expanded.extArr);
+
+  if (!found) {
+    return null;
+  }
+
+  if (expanded.extMap) {
+    found.extension = pick(expanded.extMap, found.extension);
+  }
+  return found;
+}
+
+function findFile(basedir, relpath, extArr) {
+  var noExtPath = path.resolve(basedir, relpath);
+  for (var i = 0, n = extArr.length; i < n; i++) {
+    var filepath = noExtPath + extArr[i];
+    try {
+      fs.statSync(filepath);
+      return { path: filepath, extension: extArr[i] };
+    } catch (e) {}
+  }
+
+  return null;
+}
+
+function findUpFile(basedir, filepath, extArr) {
+  var lastdir;
+  do {
+    var found = findFile(basedir, filepath, extArr);
+    if (found) {
+      return found;
+    }
+
+    lastdir = basedir;
+    basedir = path.dirname(basedir);
+  } while (lastdir !== basedir);
+
+  return null;
+}
+
+function createExtensionArray(exts) {
+  if (isString(exts)) {
+    return [exts];
+  }
+
+  if (Array.isArray(exts)) {
+    exts = exts.filter(isString);
+    return (exts.length > 0) ? exts : [''];
+  }
+
+  if (isPlainObject(exts)) {
+    exts = Object.keys(exts);
+    return (exts.length > 0) ? exts : [''];
+  }
+
+  return [''];
+}
+
+function createExtensionMap(exts) {
+  if (!isPlainObject(exts)) {
+    return null;
+  }
+
+  if (isEmpty(exts)) {
+    return { '': null };
+  }
+
+  return exts;
+}
+
+module.exports = fined;
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..bdb0193
--- /dev/null
+++ b/package.json
@@ -0,0 +1,47 @@
+{
+  "name": "fined",
+  "version": "1.0.2",
+  "description": "Find a file given a declaration of locations",
+  "author": "JS CLI Team (https://github.com/js-cli)",
+  "contributors": [
+    "Takayuki Sato <t110000508260 at yahoo.co.jp>",
+    "Blaine Bublitz <blaine.bublitz at gmail.com>"
+  ],
+  "repository": "js-cli/fined",
+  "license": "MIT",
+  "engines": {
+    "node": ">= 0.10"
+  },
+  "main": "index.js",
+  "files": [
+    "index.js",
+    "LICENSE"
+  ],
+  "scripts": {
+    "lint": "eslint . && jscs index.js test/",
+    "pretest": "npm run lint",
+    "test": "mocha --async-only",
+    "cover": "istanbul cover _mocha --report lcovonly",
+    "coveralls": "npm run cover && istanbul-coveralls"
+  },
+  "dependencies": {
+    "expand-tilde": "^1.2.1",
+    "lodash.assignwith": "^4.0.7",
+    "lodash.isempty": "^4.2.1",
+    "lodash.isplainobject": "^4.0.4",
+    "lodash.isstring": "^4.0.1",
+    "lodash.pick": "^4.2.1",
+    "parse-filepath": "^1.0.1"
+  },
+  "devDependencies": {
+    "eslint": "^1.7.3",
+    "eslint-config-gulp": "^2.0.0",
+    "expect": "^1.19.0",
+    "istanbul": "^0.4.3",
+    "istanbul-coveralls": "^1.0.3",
+    "jscs": "^2.3.5",
+    "jscs-preset-gulp": "^1.0.0",
+    "mocha": "^2.4.5"
+  },
+  "keywords": []
+}
diff --git a/test/fixtures/fined/app.js b/test/fixtures/fined/app.js
new file mode 100644
index 0000000..e69de29
diff --git a/test/fixtures/fined/appfile.js b/test/fixtures/fined/appfile.js
new file mode 100644
index 0000000..e69de29
diff --git a/test/fixtures/fined/appfile.json b/test/fixtures/fined/appfile.json
new file mode 100644
index 0000000..e69de29
diff --git a/test/fixtures/fined/index.json b/test/fixtures/fined/index.json
new file mode 100644
index 0000000..e69de29
diff --git a/test/fixtures/fined/package.json b/test/fixtures/fined/package.json
new file mode 100644
index 0000000..2c63c08
--- /dev/null
+++ b/test/fixtures/fined/package.json
@@ -0,0 +1,2 @@
+{
+}
diff --git a/test/index.js b/test/index.js
new file mode 100644
index 0000000..a1af0b5
--- /dev/null
+++ b/test/index.js
@@ -0,0 +1,1693 @@
+'use strict';
+
+var os = require('os');
+var path = require('path');
+var expect = require('expect');
+
+var cwd = process.cwd();
+var isWindows = (os.platform() === 'win32');
+
+var userHomeFile = require('./utils/get-userhome-file');
+var symlinkedFiles = require('./utils/create-symlinks');
+
+var fined = require('../');
+
+if (isWindows) {
+  // Workaround for differnce between path.resolve(winDrive) and process.cwd()
+  process.chdir(process.cwd());
+}
+
+describe('Basic behaviors', function() {
+
+  it('returns object when target file exists', function(done) {
+    var pathObj = {
+      path: 'test/fixtures/fined',
+      extensions: ['.json', '.js'],
+    };
+
+    var defaultObj = {
+      name: 'app',
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'app.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('returns null when target file does not exist', function(done) {
+    var pathObj = {
+      path: 'test/fixtures/fined',
+      extensions: ['.json', '.js'],
+    };
+
+    var defaultObj = {
+      name: 'aaa',
+      cwd: cwd,
+    };
+
+    var expected = null;
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('normalizes a string as 1st argument to an object', function(done) {
+    var pathObj = 'test/fixtures/fined';
+
+    var defaultObj = {
+      name: 'app',
+      extensions: ['.json', '.js'],
+      cwd: cwd,
+      findUp: false,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'app.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('returns null when both arguments are empty', function(done) {
+    var pathObj = {};
+
+    var defaultObj = {};
+
+    var expected = null;
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('returns null when both arguments are null', function(done) {
+    var pathObj = null;
+
+    var defaultObj = null;
+
+    var expected = null;
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('treats 1st argument as an empty object when it is invalid', function(done) {
+    var pathObj = 123;
+
+    var defaultObj = {
+      path: 'test/fixtures/fined',
+      name: 'app',
+      extensions: ['.json', '.js'],
+      cwd: cwd,
+      findUp: false,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'app.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('returns null when both arguments are invalid', function(done) {
+    var pathObj = function() {
+      return {
+        path: 'test/fixtures/fined',
+        name: 'app',
+        extensions: ['.json', '.js'],
+        cwd: cwd,
+        findUp: false,
+      };
+    };
+
+    var defaultObj = true;
+
+    var expected = null;
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+});
+
+describe('Argument defaulting', function() {
+
+  it('does not default when 2nd argument is empty', function(done) {
+    var pathObj = {
+      name: 'package',
+      path: 'test/fixtures/fined',
+      extensions: ['.json', '.js'],
+      cwd: cwd,
+      findUp: false,
+    };
+
+    var defaultObj = {};
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'package.json'),
+      extension: '.json',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('defaults all properties when 1st argument is empty', function(done) {
+    var pathObj = {};
+
+    var defaultObj = {
+      name: 'package',
+      path: 'test/fixtures/fined',
+      extensions: ['.json', '.js'],
+      cwd: cwd,
+      findUp: false,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'package.json'),
+      extension: '.json',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('defaults missing properties in 1st argument', function(done) {
+    var pathObj = {
+      name: 'app',
+      cwd: path.resolve(cwd, 'test'),
+    };
+
+    var defaultObj = {
+      path: 'fixtures/fined',
+      extensions: ['.json', '.js'],
+      findUp: false,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'app.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('defaults null properties in the 1st argument', function(done) {
+    var pathObj = {
+      name: null,
+      path: null,
+      extensions: null,
+      cwd: null,
+      findUp: null,
+    };
+
+    var defaultObj = {
+      name: 'package',
+      path: 'test/fixtures/fined',
+      extensions: ['.json', '.js'],
+      cwd: cwd,
+      findUp: false,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'package.json'),
+      extension: '.json',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('does not default when both arguments are complete', function(done) {
+    var pathObj = {
+      name: 'README',
+      path: '.',
+      extensions: ['.md', '.txt'],
+      findUp: true,
+      cwd: path.resolve(cwd, 'test/fixtures'),
+    };
+
+    var defaultObj = {
+      path: 'fixtures/fined',
+      extensions: ['.json', '.js'],
+      findUp: false,
+      name: 'app',
+      cwd: path.resolve(cwd, 'test'),
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'README.md'),
+      extension: '.md',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('defaults everything if 1st argument is null', function(done) {
+    var pathObj = null;
+
+    var defaultObj = {
+      path: 'test/fixtures/fined',
+      name: 'app',
+      extensions: ['.json', '.js'],
+      cwd: cwd,
+      findUp: false,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'app.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('ignores 2nd argument if it is null', function(done) {
+    var pathObj = {
+      path: 'test/fixtures/fined',
+      name: 'app',
+      extensions: ['.json', '.js'],
+      cwd: cwd,
+      findUp: false,
+    };
+
+    var defaultObj = null;
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'app.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('ignores 2nd argument if it is invalid', function(done) {
+    var pathObj = {
+      path: 'test/fixtures/fined',
+      name: 'app',
+      extensions: ['.json', '.js'],
+      cwd: cwd,
+      findUp: false,
+    };
+
+    var defaultObj = 123;
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'app.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+});
+
+describe('Properties: `path`', function() {
+
+  it('defaults `path` when it is null', function(done) {
+    var pathObj = {
+      path: null,
+    };
+
+    var defaultObj = {
+      path: 'fixtures/fined',
+      extensions: ['.json', '.js'],
+      findUp: false,
+      name: 'app',
+      cwd: path.resolve(cwd, 'test'),
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'app.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('returns null when `path` is null after defaulting', function(done) {
+    var pathObj = {
+      path: null,
+    };
+
+    var defaultObj = {
+      path: null,
+      extensions: ['.json', '.js'],
+      findUp: false,
+      name: 'app',
+      cwd: path.resolve(cwd, 'test'),
+    };
+
+    var expected = null;
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('resolves to cwd + name + extension when `path` is an empty string', function(done) {
+    var pathObj = {
+      path: '',
+    };
+
+    var defaultObj = {
+      extensions: ['.json', '.js'],
+      findUp: false,
+      name: 'package',
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'package.json'),
+      extension: '.json',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('resolves to cwd when `path` and `name` are empty strings', function(done) {
+    var pathObj = {
+      path: '',
+      name: '',
+    };
+
+    var defaultObj = {
+      extensions: [''],
+      findUp: false,
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd),
+      extension: '',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('returns null when `path` is an invalid type', function(done) {
+    var pathObj = {
+      path: function noop() {},
+    };
+
+    var defaultObj = {
+      extensions: ['.js', '.json'],
+      findUp: false,
+      name: 'app',
+      cwd: cwd,
+    };
+
+    var expected = null;
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('resolves properly when `path` is a String object', function(done) {
+    var pathObj = {
+      path: new String('test/fixtures/fined'),
+    };
+
+    var defaultObj = {
+      extensions: ['.js', '.json'],
+      findUp: false,
+      name: 'app',
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'app.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+
+    var pathObj2 = {
+      path: new String('test/fixtures/fined'),
+    };
+
+    var defaultObj2 = {
+      extensions: ['', '.js', '.json'],
+      findUp: false,
+      name: null,
+      cwd: cwd,
+    };
+
+    var expected2 = {
+      path: path.resolve(cwd, 'test/fixtures/fined'),
+      extension: '',
+    };
+
+    var result2 = fined(pathObj2, defaultObj2);
+
+    expect(result2).toEqual(expected2);
+    done();
+  });
+
+  it('resolves `~` to homedir', function(done) {
+    // ~
+    var pathObj = {
+      path: '~',
+    };
+
+    var defaultObj = {
+      extensions: [userHomeFile.ext],
+      findUp: false,
+      name: userHomeFile.name,
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: userHomeFile.path,
+      extension: userHomeFile.ext,
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+
+    // ~/xxx
+    var pathObj2 = {
+      path: '~/' + userHomeFile.name,
+    };
+
+    var defaultObj2 = {
+      extensions: [userHomeFile.ext],
+      findUp: false,
+      name: null,
+      cwd: cwd,
+    };
+
+    var expected2 = {
+      path: userHomeFile.path,
+      extension: userHomeFile.ext,
+    };
+
+    var result2 = fined(pathObj2, defaultObj2);
+
+    expect(result2).toEqual(expected2);
+
+    // ~xxx
+    var pathObj3 = {
+      path: '~' + userHomeFile.name,
+    };
+
+    var defaultObj3 = {
+      extensions: [userHomeFile.ext],
+      findUp: false,
+      name: null,
+      cwd: cwd,
+    };
+
+    var expected3 = {
+      path: userHomeFile.path,
+      extension: userHomeFile.ext,
+    };
+
+    var result3 = fined(pathObj3, defaultObj3);
+
+    expect(result3).toEqual(expected3);
+    done();
+  });
+
+  it('resolves `~+` to process.cwd()', function(done) {
+    // ~+
+    var pathObj = {
+      path: '~+',
+    };
+
+    var defaultObj = {
+      extensions: ['.json'],
+      findUp: false,
+      name: 'package',
+      cwd: path.resolve(cwd, 'test/fixtures/fined'),
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'package.json'),
+      extension: '.json',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+
+    // ~+/xxx
+    var pathObj2 = {
+      path: '~+/package',
+    };
+
+    var defaultObj2 = {
+      extensions: ['.json'],
+      findUp: false,
+      name: '',
+      cwd: path.resolve(cwd, 'test/fixtures/fined'),
+    };
+
+    var expected2 = {
+      path: path.resolve(cwd, 'package.json'),
+      extension: '.json',
+    };
+
+    var result2 = fined(pathObj2, defaultObj2);
+
+    expect(result2).toEqual(expected2);
+
+    // ~+xxx
+    var pathObj3 = {
+      path: '~+package',
+    };
+
+    var defaultObj3 = {
+      extensions: ['.json'],
+      findUp: false,
+      name: '',
+      cwd: path.resolve(cwd, 'test/fixtures/fined'),
+    };
+
+    var expected3 = {
+      path: path.resolve(cwd, 'package.json'),
+      extension: '.json',
+    };
+
+    var result3 = fined(pathObj3, defaultObj3);
+
+    expect(result3).toEqual(expected3);
+    done();
+  });
+
+  it('ignores `cwd` when `path` is absolute', function(done) {
+    var pathObj = {
+      path: cwd,
+      cwd: path.resolve(cwd, 'test/fixtures/fined'),
+    };
+
+    var defaultObj = {
+      extensions: ['.json'],
+      findUp: false,
+      name: 'package',
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'package.json'),
+      extension: '.json',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('ignores `cwd` when `path` has a drive letter (Windows only)', function(done) {
+    if (!isWindows) {
+      this.skip();
+      return;
+    }
+
+    var winDrive = cwd.slice(0, 2);
+
+    var pathObj = {
+      path: winDrive + 'test\\fixtures\\fined',
+    };
+
+    var defaultObj = {
+      name: 'app',
+      findUp: false,
+      extensions: ['.js'],
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'app.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+});
+
+describe('Properties: `name`', function() {
+
+  it('ignores `name` when null', function(done) {
+    var pathObj = {
+      name: null,
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures/fined',
+      extensions: [''],
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined'),
+      extension: '',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('ignores `name` when it is an empty string', function(done) {
+    var pathObj = {
+      name: '',
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures/fined',
+      extensions: [''],
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined'),
+      extension: '',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('ignores `name` when it is an invalid type', function(done) {
+    var pathObj = {
+      name: 123,
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures/fined',
+      extensions: [''],
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined'),
+      extension: '',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('searches for file with `name` when it is a String object', function(done) {
+    var pathObj = {
+      name: new String('app'),
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures/fined',
+      extensions: ['.js'],
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'app.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+
+    var pathObj2 = {
+      name: new String('package'),
+    };
+
+    var defaultObj2 = {
+      path: '',
+      extensions: ['.json'],
+      cwd: cwd,
+    };
+
+    var expected2 = {
+      path: path.resolve(cwd, 'package.json'),
+      extension: '.json',
+    };
+
+    var result2 = fined(pathObj2, defaultObj2);
+
+    expect(result2).toEqual(expected2);
+    done();
+  });
+
+  it('resolves `name` even when it is a directory', function(done) {
+    var pathObj = {
+      name: 'fined',
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures',
+      extensions: [''],
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures', 'fined'),
+      extension: '',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('resolves `name` when it is an absolute path and `path` is empty', function(done) {
+    var pathObj = {
+      name: path.resolve(cwd, 'test/fixtures/fined/app'),
+    };
+
+    var defaultObj = {
+      path: '',
+      extensions: ['.js'],
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined/app.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+
+    var pathObj2 = {
+      name: path.join(userHomeFile.dir, userHomeFile.name),
+    };
+
+    var defaultObj2 = {
+      path: '',
+      extensions: [userHomeFile.ext],
+      cwd: cwd,
+    };
+
+    var expected2 = {
+      path: userHomeFile.path,
+      extension: userHomeFile.ext,
+    };
+
+    var result2 = fined(pathObj2, defaultObj2);
+
+    expect(result2).toEqual(expected2);
+    done();
+  });
+
+  it('returns null when `name` is an absolute path but `path` is not empty', function(done) {
+    var pathObj = {
+      name: path.resolve(cwd, 'test/fixtures/fined/app'),
+      path: 'test/fixtures/fined',
+    };
+
+    var defaultObj = {
+      extensions: ['.js'],
+      cwd: cwd,
+    };
+
+    var expected = null;
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('will not expand `~` as part of `name`', function(done) {
+    var pathObj = {
+      name: '~/' + userHomeFile.name,
+    };
+
+    var defaultObj = {
+      path: '',
+      extensions: [userHomeFile.ext],
+      cwd: cwd,
+    };
+
+    var expected = null;
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+});
+
+describe('Properties: `extensions`', function() {
+
+  it('resolves to the extension if it is a string', function(done) {
+    var pathObj = {
+      extensions: '.js',
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures/fined',
+      name: 'app',
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'app.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('resolves to the first found extension if it is an array', function(done) {
+    var pathObj = {
+      extensions: ['.json', '.txt', '.js'],
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures/fined',
+      name: 'app',
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'app.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('resolves to the first found extension if it is an object', function(done) {
+    var pathObj = {
+      extensions: {
+        '.json': 1,
+        '.js': 2,
+        '.txt': 3,
+        '.yml': 4,
+      },
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures/fined',
+      name: 'app',
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'app.js'),
+      extension: { '.js': 2 },
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('resolves to the first found extension if multiple match', function(done) {
+    var pathObj = {
+      extensions: ['.json', '.js'],
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures/fined',
+      name: 'appfile',
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'appfile.json'),
+      extension: '.json',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+
+    var pathObj2 = {
+      extensions: ['.js', '.json'],
+    };
+
+    var defaultObj2 = {
+      path: 'test/fixtures/fined',
+      name: 'appfile',
+      cwd: cwd,
+    };
+
+    var expected2 = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'appfile.js'),
+      extension: '.js',
+    };
+
+    var result2 = fined(pathObj2, defaultObj2);
+
+    expect(result2).toEqual(expected2);
+    done();
+  });
+
+  it('treats a null value as an empty array', function(done) {
+    var pathObj = {
+      extensions: null,
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures',
+      name: 'fined',
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures', 'fined'),
+      extension: '',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('treats an empty string value as an empty array', function(done) {
+    var pathObj = {
+      extensions: '',
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures',
+      name: 'fined',
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures', 'fined'),
+      extension: '',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('treats an empty array as an empty array', function(done) {
+    var pathObj = {
+      extensions: [],
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures',
+      name: 'fined',
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures', 'fined'),
+      extension: '',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('treats an empty object as an object with only key being an empty string', function(done) {
+    var pathObj = {
+      extensions: {},
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures',
+      name: 'fined',
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures', 'fined'),
+      extension: { '': null },
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('treats an invalid type as an empty array', function(done) {
+    var pathObj = {
+      extensions: 123,
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures',
+      name: 'fined',
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures', 'fined'),
+      extension: '',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('supports String objects', function(done) {
+    var pathObj = {
+      extensions: [new String('.json'), new String('.js')],
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures/fined',
+      name: 'app',
+      cwd: cwd,
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'app.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+
+    var exts = {};
+    exts[new String('.json')] = 1;
+    exts[new String('.js')] = 2;
+
+    var pathObj2 = {
+      extensions: exts,
+    };
+
+    var defaultObj2 = {
+      path: 'test/fixtures/fined',
+      name: 'app',
+      cwd: cwd,
+    };
+
+    var expected2 = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'app.js'),
+      extension: { '.js': 2 },
+    };
+
+    var result2 = fined(pathObj2, defaultObj2);
+
+    expect(result2).toEqual(expected2);
+    done();
+  });
+});
+
+describe('Properties: `cwd`', function() {
+
+  it('can be absolute', function(done) {
+    var pathObj = {
+      cwd: path.resolve('.'),
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures/fined',
+      name: 'appfile',
+      extensions: '.js',
+    };
+
+    var expected = {
+      path: path.resolve('.', 'test/fixtures/fined/appfile.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('can be relative', function(done) {
+    var pathObj = {
+      cwd: '.',
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures/fined',
+      name: 'appfile',
+      extensions: '.js',
+    };
+
+    var expected = {
+      path: path.resolve('.', 'test/fixtures/fined/appfile.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+
+    var pathObj2 = {
+      cwd: 'test/fixtures',
+    };
+
+    var defaultObj2 = {
+      path: 'fined',
+      name: 'appfile',
+      extensions: '.js',
+    };
+
+    var expected2 = {
+      path: path.resolve('.', 'test/fixtures/fined/appfile.js'),
+      extension: '.js',
+    };
+
+    var result2 = fined(pathObj2, defaultObj2);
+
+    expect(result2).toEqual(expected2);
+    done();
+  });
+
+  it('treats a null value as `.`', function(done) {
+    var pathObj = {
+      cwd: null,
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures/fined',
+      name: 'appfile',
+      extensions: '.js',
+    };
+
+    var expected = {
+      path: path.resolve('.', 'test/fixtures/fined/appfile.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('treats an empty string as `.`', function(done) {
+    var pathObj = {
+      cwd: '',
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures/fined',
+      name: 'appfile',
+      extensions: '.js',
+    };
+
+    var expected = {
+      path: path.resolve('.', 'test/fixtures/fined/appfile.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('treats an invalid type as `.`', function(done) {
+    var pathObj = {
+      cwd: 123,
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures/fined',
+      name: 'appfile',
+      extensions: '.js',
+    };
+
+    var expected = {
+      path: path.resolve('.', 'test/fixtures/fined/appfile.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('supports String objects', function(done) {
+    var pathObj = {
+      cwd: new String(cwd),
+    };
+
+    var defaultObj = {
+      path: 'test/fixtures/fined',
+      name: 'appfile',
+      extensions: '.js',
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined/appfile.js'),
+      extension: '.js',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('expands `~` to homedir', function(done) {
+    var pathObj = {
+      cwd: '~',
+    };
+
+    var defaultObj = {
+      path: '',
+      name: userHomeFile.name,
+      extensions: userHomeFile.ext,
+    };
+
+    var expected = {
+      path: userHomeFile.path,
+      extension: userHomeFile.ext,
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+});
+
+describe('Properties: `findUp`', function() {
+
+  it('finds a file up in the tree', function(done) {
+    var pathObj = {
+      path: '',
+      findUp: true,
+    };
+
+    var defaultObj = {
+      name: 'README',
+      extensions: ['.md'],
+      cwd: 'test/fixtures/fined',
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'README.md'),
+      extension: '.md',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('finds a directory up in the tree', function(done) {
+    var pathObj = {
+      path: '',
+      findUp: true,
+    };
+
+    var defaultObj = {
+      name: 'test',
+      extensions: ['.md', ''],
+      cwd: 'fixtures/fined',
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test'),
+      extension: '',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('does not search up the tree if file exists in cwd', function(done) {
+    var pathObj = {
+      path: '',
+      extensions: '.json',
+      findUp: true,
+    };
+
+    var defaultObj = {
+      name: 'package',
+      cwd: 'test/fixtures/fined',
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined', 'package.json'),
+      extension: '.json',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('does not search up the tree if `path` is absolute', function(done) {
+    var pathObj = {
+      findUp: true,
+      path: path.resolve(cwd, 'test'),
+      extensions: '.md',
+    };
+
+    var defaultObj = {
+      name: 'README',
+      cwd: path.resolve(cwd, 'test'),
+    };
+
+    var expected = null;
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('does not search up the tree if `cwd` has a drive letter (Windows only)', function(done) {
+    if (!isWindows) {
+      this.skip();
+      return;
+    }
+
+    var winDrive = cwd.slice(0, 2);
+
+    var pathObj = {
+      findUp: true,
+      name: 'package',
+      path: '',
+      cwd: winDrive + 'test\\fixtures',
+      extensions: '.json',
+    };
+
+    var defaultObj = {};
+
+    var expected = {
+      path: path.resolve(cwd, 'package.json'),
+      extension: '.json',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+
+  it('does not search up the tree any more if file with another extension candidate exists', function(done) {
+    var pathObj = {
+      findUp: true,
+      path: '.',
+      extensions: ['.js', '.json'],
+    };
+
+    var defaultObj = {
+      name: 'index',
+      cwd: path.resolve(cwd, 'test/fixtures/fined'),
+    };
+
+    var expected = {
+      path: path.resolve(cwd, 'test/fixtures/fined/index.json'),
+      extension: '.json',
+    };
+
+    var result = fined(pathObj, defaultObj);
+
+    expect(result).toEqual(expected);
+    done();
+  });
+});
+
+describe('Symbolic links', function() {
+
+  it('returns symlink path when found link points to a file', function(done) {
+    var pathObj = {
+      path: '.',
+      name: symlinkedFiles[0].name,
+      extensions: [symlinkedFiles[0].ext],
+      cwd: symlinkedFiles[0].dir,
+    };
+
+    var expected = {
+      path: symlinkedFiles[0].path,
+      extension: symlinkedFiles[0].ext,
+    };
+
+    var result = fined(pathObj);
+
+    expect(result).toEqual(expected);
+
+    var pathObj2 = {
+      path: '.',
+      name: symlinkedFiles[1].name,
+      extensions: [symlinkedFiles[1].ext],
+      cwd: symlinkedFiles[1].dir,
+    };
+
+    var expected2 = {
+      path: symlinkedFiles[1].path,
+      extension: symlinkedFiles[1].ext,
+    };
+
+    var result2 = fined(pathObj2);
+
+    expect(result2).toEqual(expected2);
+    done();
+  });
+
+  it('returns symlink path when found link points to a directory', function(done) {
+    var pathObj = {
+      path: '.',
+      name: symlinkedFiles[4].name,
+      extensions: [symlinkedFiles[4].ext],
+      cwd: symlinkedFiles[4].dir,
+    };
+
+    var expected = {
+      path: symlinkedFiles[4].path,
+      extension: symlinkedFiles[4].ext,
+    };
+
+    var result = fined(pathObj);
+
+    expect(result).toEqual(expected);
+
+    var pathObj2 = {
+      path: '.',
+      name: symlinkedFiles[5].name,
+      extensions: [symlinkedFiles[5].ext],
+      cwd: symlinkedFiles[5].dir,
+    };
+
+    var expected2 = {
+      path: symlinkedFiles[5].path,
+      extension: symlinkedFiles[5].ext,
+    };
+
+    var result2 = fined(pathObj2);
+
+    expect(result2).toEqual(expected2);
+    done();
+  });
+
+  it('returns null when found link is an invalid symlink', function(done) {
+    var pathObj = {
+      path: '.',
+      name: symlinkedFiles[2].name,
+      extensions: [symlinkedFiles[2].ext],
+      cwd: symlinkedFiles[2].dir,
+    };
+
+    var expected = null;
+
+    var result = fined(pathObj);
+
+    expect(result).toEqual(expected);
+
+    var pathObj2 = {
+      path: '.',
+      name: symlinkedFiles[3].name,
+      extensions: [symlinkedFiles[3].ext],
+      cwd: symlinkedFiles[3].dir,
+    };
+
+    var expected2 = null;
+
+    var result2 = fined(pathObj2);
+
+    expect(result2).toEqual(expected2);
+    done();
+  });
+
+  it('returns symlink path during findUp when symlink points to a file', function(done) {
+    var pathObj = {
+      path: path.basename(symlinkedFiles[0].dir),
+      name: symlinkedFiles[0].name,
+      extensions: [symlinkedFiles[0].ext],
+      cwd: symlinkedFiles[0].dir,
+      findUp: true,
+    };
+
+    var expected = {
+      path: symlinkedFiles[0].path,
+      extension: symlinkedFiles[0].ext,
+    };
+
+    var result = fined(pathObj);
+
+    expect(result).toEqual(expected);
+
+    var pathObj2 = {
+      path: path.basename(symlinkedFiles[1].dir),
+      name: symlinkedFiles[1].name,
+      extensions: [symlinkedFiles[1].ext],
+      cwd: symlinkedFiles[1].dir,
+      findUp: true,
+    };
+
+    var expected2 = {
+      path: symlinkedFiles[1].path,
+      extension: symlinkedFiles[1].ext,
+    };
+
+    var result2 = fined(pathObj2);
+
+    expect(result2).toEqual(expected2);
+    done();
+  });
+
+  it('returns symlink path during findUp when symlink points to a directory', function(done) {
+    var pathObj = {
+      path: path.basename(symlinkedFiles[4].dir),
+      name: symlinkedFiles[4].name,
+      extensions: [symlinkedFiles[4].ext],
+      cwd: symlinkedFiles[4].dir,
+      findUp: true,
+    };
+
+    var expected = {
+      path: symlinkedFiles[4].path,
+      extension: symlinkedFiles[4].ext,
+    };
+
+    var result = fined(pathObj);
+
+    expect(result).toEqual(expected);
+
+    var pathObj2 = {
+      path: path.basename(symlinkedFiles[5].dir),
+      name: symlinkedFiles[5].name,
+      extensions: [symlinkedFiles[5].ext],
+      cwd: symlinkedFiles[5].dir,
+      findUp: true,
+    };
+
+    var expected2 = {
+      path: symlinkedFiles[5].path,
+      extension: symlinkedFiles[5].ext,
+    };
+
+    var result2 = fined(pathObj2);
+
+    expect(result2).toEqual(expected2);
+    done();
+  });
+
+  it('returns null during findUp when symlink is invalid', function(done) {
+    var pathObj = {
+      path: path.basename(symlinkedFiles[2].dir),
+      name: symlinkedFiles[2].name,
+      extensions: [symlinkedFiles[2].ext],
+      cwd: symlinkedFiles[2].dir,
+      findUp: true,
+    };
+
+    var expected = null;
+
+    var result = fined(pathObj);
+
+    expect(result).toEqual(expected);
+
+    var pathObj2 = {
+      path: path.basename(symlinkedFiles[3].dir),
+      name: symlinkedFiles[3].name,
+      extensions: [symlinkedFiles[3].ext],
+      cwd: symlinkedFiles[3].dir,
+      findUp: true,
+    };
+
+    var expected2 = null;
+
+    var result2 = fined(pathObj2);
+
+    expect(result2).toEqual(expected2);
+    done();
+  });
+});
diff --git a/test/utils/create-symlinks.js b/test/utils/create-symlinks.js
new file mode 100644
index 0000000..cc88c94
--- /dev/null
+++ b/test/utils/create-symlinks.js
@@ -0,0 +1,33 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+
+var dir = path.resolve(__dirname, '../fixtures/fined');
+var basedir = path.resolve(__dirname, '../../');
+
+var symlinkedFiles = [0,1,2,3,4,5].map(function(v, j) {
+  return path.resolve(dir, 'symlink' + j + '.json');
+});
+
+if (fs.existsSync(symlinkedFiles[0])) {
+  for (var i0 = symlinkedFiles.length - 1; i0 >= 0; i0--) {
+    fs.unlinkSync(symlinkedFiles[i0]);
+  }
+}
+
+var linkedFiles = ['package.json', 'xxxx', 'test/'];
+for (var i = 0, n = linkedFiles.length; i < n; i++) {
+  fs.symlinkSync(path.resolve(basedir, linkedFiles[i]), symlinkedFiles[i * 2]);
+  fs.symlinkSync(symlinkedFiles[i * 2], symlinkedFiles[i * 2 + 1]);
+}
+
+module.exports = symlinkedFiles.map(function(pth) {
+  var ext = path.extname(pth);
+  return {
+    path: pth,
+    dir: path.dirname(pth),
+    ext: ext,
+    name: path.basename(pth, ext),
+  };
+});
diff --git a/test/utils/get-userhome-file.js b/test/utils/get-userhome-file.js
new file mode 100644
index 0000000..a3afa60
--- /dev/null
+++ b/test/utils/get-userhome-file.js
@@ -0,0 +1,25 @@
+'use strict';
+
+var fs = require('fs');
+var path = require('path');
+var expandTilde = require('expand-tilde');
+
+var userHomeDir = expandTilde('~');
+var userHomeFiles = fs.readdirSync(userHomeDir);
+
+var userHomeFilePath, userHomeFileExt, userHomeFileName, userHomeFileDir;
+
+if (userHomeFiles.length > 0) {
+  var filePath = path.resolve(userHomeDir, userHomeFiles[0]);
+  userHomeFilePath = filePath;
+  userHomeFileDir = path.dirname(userHomeFilePath);
+  userHomeFileExt = path.extname(userHomeFilePath);
+  userHomeFileName = path.basename(userHomeFilePath, userHomeFileExt);
+}
+
+module.exports = {
+  path: userHomeFilePath,
+  name: userHomeFileName,
+  ext:  userHomeFileExt,
+  dir:  userHomeFileDir,
+};

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-fined.git



More information about the Pkg-javascript-commits mailing list