diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3af7524 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +doc/ +out/ +.idea/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..e4cb108 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +appdirsjs \ No newline at end of file diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml new file mode 100644 index 0000000..3003ed0 --- /dev/null +++ b/.idea/codeStyleSettings.xml @@ -0,0 +1,45 @@ + + + + + + + diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..217af47 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,23 @@ + + + + + + diff --git a/.idea/copyright/dlee.xml b/.idea/copyright/dlee.xml new file mode 100644 index 0000000..7c276a9 --- /dev/null +++ b/.idea/copyright/dlee.xml @@ -0,0 +1,9 @@ + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..0ac7f1a --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,9 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..e206d70 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..a491edf --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,15 @@ + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/profiles_settings.xml b/.idea/inspectionProfiles/profiles_settings.xml new file mode 100644 index 0000000..3b31283 --- /dev/null +++ b/.idea/inspectionProfiles/profiles_settings.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/.idea/jsLibraryMappings.xml b/.idea/jsLibraryMappings.xml new file mode 100644 index 0000000..a9b7b7a --- /dev/null +++ b/.idea/jsLibraryMappings.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.idea/jsLinters/jshint.xml b/.idea/jsLinters/jshint.xml new file mode 100644 index 0000000..10d8343 --- /dev/null +++ b/.idea/jsLinters/jshint.xml @@ -0,0 +1,68 @@ + + + + + + diff --git a/.idea/libraries/Node_js_Dependencies_for_appdirsjs.xml b/.idea/libraries/Node_js_Dependencies_for_appdirsjs.xml new file mode 100644 index 0000000..efd5554 --- /dev/null +++ b/.idea/libraries/Node_js_Dependencies_for_appdirsjs.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..39b9d1f --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..781b360 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.idea/scopes/scope_settings.xml b/.idea/scopes/scope_settings.xml new file mode 100644 index 0000000..922003b --- /dev/null +++ b/.idea/scopes/scope_settings.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..275077f --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/.jshintignore b/.jshintignore new file mode 100644 index 0000000..62083d5 --- /dev/null +++ b/.jshintignore @@ -0,0 +1,2 @@ +node_modules/** +out/** diff --git a/.jshintrc b/.jshintrc new file mode 100644 index 0000000..e0372a8 --- /dev/null +++ b/.jshintrc @@ -0,0 +1,52 @@ +/* From https://github.com/airbnb/javascript/blob/master/linters/jshintrc */ +{ + /* + * ENVIRONMENTS + * ================= + */ + + // Define globals exposed by Node.js. + "node": true, + + /* + * ENFORCING OPTIONS + * ================= + */ + + // Force all variable names to use either camelCase style or UPPER_CASE + // with underscores. + "camelcase": true, + + // Prohibit use of == and != in favor of === and !==. + "eqeqeq": true, + + // Suppress warnings about == null comparisons. + "eqnull": true, + + // Enforce tab width of 2 spaces. + "indent": 2, + + // Prohibit use of a variable before it is defined. + "latedef": true, + + // Require capitalized names for constructor functions. + "newcap": true, + + // Enforce use of single quotation marks for strings. + "quotmark": "single", + + // Prohibit trailing whitespace. + "trailing": true, + + // Prohibit use of explicitly undeclared variables. + "undef": true, + + // Warn when variables are defined but never used. + "unused": true, + + // Enforce line length to 80 characters + "maxlen": 80, + + // Enforce placing 'use strict' at the top function scope + "strict": true +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..fc2f6dc --- /dev/null +++ b/README.md @@ -0,0 +1,35 @@ +# AppDirs.js + +> The wonderful thing about standards is that there are so many of them to +> choose from. + + -- _Andrew Tanenbaum_ + +When it comes to storing application data, the convention on where to store +your data varies from platform to platform. + +This package is a port of the Python [appdirs][] library, which provides a small +set of methods which can be used to locate the preferred directories for user +and site data for an application. + +It currently supports OS X and Unix operating systems (Unix support is +according to the [XDG specification][]). Windows support is not yet +implemented, but a pull request adding that would be greatly appreciated! + +## Directories + +The directories the AppDirs.js can help you locate are: + + * user data dir (`user_data_dir`) + * user config dir (`user_config_dir`) + * user cache dir (`user_cache_dir`) + * site data dir (`site_data_dir`) + * site config dir (`site_config_dir`) + * user log dir (`user_log_dir`) + +## Usage + +See the JSDocs for specifics on using the API. + + [appdirs]: https://github.com/ActiveState/appdirs + [xdg specification]: http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html diff --git a/appdirsjs.iml b/appdirsjs.iml new file mode 100644 index 0000000..c529157 --- /dev/null +++ b/appdirsjs.iml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/index.js b/index.js new file mode 100644 index 0000000..39e1c6f --- /dev/null +++ b/index.js @@ -0,0 +1,399 @@ +// Copyright (c) 2014. David M. Lee, II. +/*jshint unused:vars */ +'use strict'; + +/** + * Platform specific directory locator. + * + * The API's all follow the same general pattern: + * + * @module appdirs + */ + +var os = require('os'), + path = require('path'); + +/** + * Append the name and and version to a path. + * + * Both the appname and version are optional. The version is only appended if + * the appname. + * + * @param {string} dir Base directory. + * @param {string} [appname] Optional name to append. + * @param {string} [version] Optional version to append. + * @returns {string} Resulting path + * @private + */ +var appendNameVersion = function (dir, appname, version) { + if (appname) { + dir = path.join(dir, appname); + if (version) { + dir = path.join(dir, version); + } + } + return dir; +}; + +var windows = { + // Judging from appdirs.py, Windows support is quite complicated. + // Maybe another time... + userDataDir: function (appname, appauthor, version, roaming) { + throw new Error('Unimplemented'); + }, + userConfigDir: function (appname, appauthor, version, roaming) { + throw new Error('Unimplemented'); + }, + userCacheDir: function (appname, appauthor, version) { + throw new Error('Unimplemented'); + }, + siteDataDir: function (appname, appauthor, version, multipath) { + throw new Error('Unimplemented'); + }, + siteConfigDir: function (appname, appauthor, version, multipath) { + throw new Error('Unimplemented'); + }, + userLogDir: function (appname, appauthor, version) { + throw new Error('Unimplemented'); + } +}; + +var darwin = { + userDataDir: function (appname, appauthor, version, roaming) { + var dir = path.join(process.env.HOME, 'Library/Application Support'); + return appendNameVersion(dir, appname, version); + }, + userConfigDir: function (appname, appauthor, version, roaming) { + return darwin.userDataDir(appname, appauthor, version, roaming); + }, + userCacheDir: function (appname, appauthor, version) { + var dir = path.join(process.env.HOME, 'Library/Caches'); + return appendNameVersion(dir, appname, version); + }, + siteDataDir: function (appname, appauthor, version, multipath) { + var dir = appendNameVersion('/Library/Application Support', appname, version); + if (multipath) { + return [dir]; + } + return dir; + }, + siteConfigDir: function (appname, appauthor, version, multipath) { + return darwin.siteDataDir(appname, appauthor, version, multipath); + }, + userLogDir: function (appname, appauthor, version) { + var dir = path.join(process.env.HOME, 'Library/Logs'); + return appendNameVersion(dir, appname, version); + } +}; + +var xdg = { + userDataDir: function (appname, appauthor, version, roaming) { + var dir = process.env.XDG_DATA_HOME || + path.join(process.env.HOME, '.local/share'); + return appendNameVersion(dir, appname, version); + }, + userConfigDir: function (appname, appauthor, version, roaming) { + var dir = process.env.XDG_CONFIG_HOME || + path.join(process.env.HOME, '.config'); + return appendNameVersion(dir, appname, version); + }, + userCacheDir: function (appname, appauthor, version) { + var dir = process.env.XDG_CACHE_HOME || + path.join(process.env.HOME, '.cache'); + return appendNameVersion(dir, appname, version); + }, + siteDataDir: function (appname, appauthor, version, multipath) { + var dirstr = process.env.XDG_DATA_DIRS || + ['/usr/local/share', '/usr/share'].join(path.delimiter), + dirs = dirstr.split(path.delimiter).map(function (dir) { + return appendNameVersion(dir, appname, version); + }); + if (multipath) { + return dirs; + } else { + return dirs[0]; + } + }, + siteConfigDir: function (appname, appauthor, version, multipath) { + var dirstr = process.env.XDG_CONFIG_DIRS || '/etc/xdg', + dirs = dirstr.split(path.delimiter).map(function (dir) { + return appendNameVersion(dir, appname, version); + }); + if (multipath) { + return dirs; + } else { + return dirs[0]; + } + }, + userLogDir: function (appname, appauthor, version) { + var cacheDir = xdg.userCacheDir(appname, appauthor, version); + return path.join(cacheDir, 'log'); + } +}; + +var impl = (function () { + switch (os.platform()) { + case 'win32': + return windows; + case 'darwin': + return darwin; + default: + return xdg; + } +})(); + +/** + * Build an AppDirs convenience object. + * + * @param {string} appname Application name. + * @param {string} [appauthor] Application author. Defaults to appname. + * @param {string} [version] Application version. + * @param {boolean} [roaming] If true, use directory for roaming profile. + * @param {boolean} [multipath] If true, return arrays for multipath functions + * (siteDataDir, siteConfigDir). + * @constructor + */ +var AppDirs = + function AppDirs(appname, appauthor, version, roaming, multipath) { + this.appname = appname; + this.appauthor = appauthor; + this.version = version; + this.roaming = roaming; + this.multipath = multipath; + }; + +/** + * User data directory. + * @returns {string} + */ +AppDirs.prototype.userDataDir = function () { + return impl.userDataDir(this.appname, this.appauthor, this.version, + this.roaming); +}; + +/** + * User configuration directory. + * @returns {string} + */ +AppDirs.prototype.userConfigDir = function () { + return impl.userConfigDir(this.appname, this.appauthor, this.version, + this.roaming); +}; + +/** + * User cache directory. + * @returns {string} + */ +AppDirs.prototype.userCacheDir = function () { + return impl.userCacheDir(this.appname, this.appauthor, this.version); +}; + +/** + * Site data directory. + * @returns {string} + */ +AppDirs.prototype.siteDataDir = function () { + return impl.siteDataDir(this.appname, this.appauthor, this.version, + this.multipath); +}; + +/** + * Site configuration directory. + * @returns {string} + */ +AppDirs.prototype.siteConfigDir = function () { + return impl.siteConfigDir(this.appname, this.appauthor, this.version, + this.multipath); +}; + +/** + * User log directory. + * @returns {string} + */ +AppDirs.prototype.userLogDir = function () { + return impl.userLogDir(this.appname, this.appauthor, this.version); +}; + +module.exports = { + /*jshint maxlen:false */ + /** + * Windows appdirs implementation. (unimplemented) + * + * The standard directory structure for Windows can be found on + * [MSDN]{@link http://support.microsoft.com/default.aspx?scid=kb;en-us;310294#XSLTH3194121123120121120120}. + */ + windows: windows, + /** + * OS X appdirs implementation. + * + * The standard directory structure for OS X can be found on + * [the apple developer site]{@link https://developer.apple.com/library/mac/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/FileSystemOverview/FileSystemOverview.html}. + */ + darwin: darwin, + /** + * XDG appdirs implementation. + * + * The is the standard directory structure appdirs uses for *NIX operating + * systems. The XDG spec can be found on + * [the FreeDesktop standards site]{@link http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html}. + */ + xdg: xdg, + /*jshint maxlen:80 */ + + /** + * Return full path to the user-specific data dir for this application. + * + * Typical user cache directories are: + *
+ *
Mac OS X
+ *
~/Library/Application Support/{AppName}
+ *
Unix
+ *
~/.local/share/{AppName}/log
+ *
Win 7 (not roaming)
+ *
C:\Users\{username}\AppData\Local\{AppAuthor}\{AppName}
+ *
Win 7 (roaming)
+ *
C:\Users\{username}\AppData\Roaming\{AppAuthor}\{AppName}
+ *
+ * + * @param {string} [appname] Application name. If not give, then the base user + * data directory is returned. + * @param {string} [appauthor] Application author's name. This falls back to + * appname. + * @param {string} [version] Optional version to append to the path. Only + * applied when appname is present. + * @param {boolean} [roaming] When set, use the Windows roaming + * appdata directory + * @returns {string} User data directory. + * @function + */ + userDataDir: impl.userDataDir, + /** + * Return full path to the user-specific config dir for this application. + * + * Typical user data directories are: + *
+ *
Mac OS X
+ *
same as user_data_dir
+ *
Unix
+ *
~/.config/{AppName}
+ *
Windows
+ *
same as user_data_dir
+ *
+ * + * @param {string} [appname] Application name. If not give, then the base user + * config directory is returned. + * @param {string} [appauthor] Application author's name. This falls back to + * appname. + * @param {string} [version] Optional version to append to the path. Only + * applied when appname is present. + * @param {boolean} [roaming] When set, use the Windows roaming + * appdata directory + * @returns {string} User config directory. + * @function + */ + userConfigDir: impl.userConfigDir, + /** + * Return full path to the user-specific cache dir for this application. + * + * Typical user cache directories are: + *
+ *
Mac OS X
+ *
~/Library/Caches/{AppName}
+ *
Unix
+ *
~/.cache/{AppName}
+ *
+ * + * @param {string} [appname] Application name. If not give, then the base user + * cache directory is returned. + * @param {string} [appauthor] Application author's name. This falls back to + * appname. + * @param {string} [version] Optional version to append to the path. Only + * applied when appname is present. + * @returns {string} User cache directory + * @function + */ + userCacheDir: impl.userCacheDir, + /** + * Return full path to the user-shared data dir for this application. + * + * Typical site data directories are: + *
+ *
Mac OS X
+ *
/Library/Application Support/{AppName}
+ *
Unix
+ *
/usr/local/share/{AppName} or /usr/share/{AppName}
+ *
+ * + * @param {string} [appname] Application name. If not give, then the base site + * data directory is returned. + * @param {string} [appauthor] Application author's name. This falls back to + * appname. + * @param {string} [version] Optional version to append to the path. Only + * applied when appname is present. + * @param {boolean} [multipath] If true, on *NIX, all site data dirs are + * returned. + * @returns {string} Site data directory. + * @function + */ + siteDataDir: impl.siteDataDir, + /** + * Return full path to the user-shared config dir for this application. + * + * Typical user data directories are: + *
+ *
Mac OS X
+ *
same as site_data_dir
+ *
Unix
+ *
/etc/xdg/{AppName}
+ *
Windows
+ *
same as site_data_dir
+ *
+ * + * @param {string} [appname] Application name. If not give, then the base site + * data directory is returned. + * @param {string} [appauthor] Application author's name. This falls back to + * appname. + * @param {string} [version] Optional version to append to the path. Only + * applied when appname is present. + * @param {boolean} [multipath] If true, on *NIX, all site data dirs are + * returned. + * @returns {string} Site config directory. + * @function + */ + siteConfigDir: impl.siteConfigDir, + /** + * Return full path to the user-specific log dir for this application. + * + * Typical user cache directories are: + *
+ *
Mac OS X
+ *
~/Library/Logs/{AppName}
+ *
Unix
+ *
~/.cache/{AppName}/log
+ *
+ * + * @param {string} [appname] Application name. If not give, then the base site + * data directory is returned. + * @param {string} [appauthor] Application author's name. This falls back to + * appname. + * @param {string} [version] Optional version to append to the path. Only + * applied when appname is present. + * @returns {string} User log directory. + * @function + */ + userLogDir: impl.userLogDir, + + AppDirs: AppDirs +}; diff --git a/package.json b/package.json new file mode 100644 index 0000000..12bc425 --- /dev/null +++ b/package.json @@ -0,0 +1,38 @@ +{ + "name": "appdirsjs", + "version": "0.0.1", + "author": "David M. Lee, II ", + "description": "Node.js port of appdirs", + "homepage": "https://github.com/building5/appdirsjs", + "scripts": { + "jsdoc": "jsdoc README.md index.js", + "jshint": "jshint .", + "test": "_mocha" + }, + "repository": { + "type": "git", + "url": "https://github.com/building5/appdirsjs.git" + }, + "keywords": [ + "configuration" + ], + "dependencies": {}, + "devDependencies": { + "mocha": "^1.17.1", + "chai": "^1.9.0", + "blanket": "^1.1.6", + "jshint": "^2.4.4", + "jsdoc": "^3.3.0-alpha4" + }, + "license": "MIT", + "engines": { + "node": ">=0.10" + }, + "config": { + "blanket": { + "data-cover-never": [ + "node_modules" + ] + } + } +} diff --git a/test/darwin.spec.js b/test/darwin.spec.js new file mode 100644 index 0000000..a7dd8fa --- /dev/null +++ b/test/darwin.spec.js @@ -0,0 +1,146 @@ +// Copyright (c) 2014. David M. Lee, II. +/* global before, after, describe, it */ +/* jshint expr:true */ +'use strict'; + +var appdirs = require('..'), + chai = require('chai'), + expect = chai.expect; + +chai.Assertion.includeStack = true; + +describe('AppDirs on Mac', function () { + var homeOrig, + uut = appdirs.darwin; + + before(function () { + homeOrig = process.env.HOME; + process.env.HOME = '/Users/fake-home'; + }); + + after(function () { + process.env.HOME = homeOrig; + }); + + describe('userDataDir', function () { + it('should default to ~/Library/Application Support', function () { + expect(uut.userDataDir()).to.equal( + '/Users/fake-home/Library/Application Support'); + }); + it('should include appname', function () { + expect(uut.userDataDir('someApp')).to.equal( + '/Users/fake-home/Library/Application Support/someApp'); + }); + it('should include version', function () { + expect(uut.userDataDir('someApp', null, '3.1')).to.equal( + '/Users/fake-home/Library/Application Support/someApp/3.1'); + }); + it('should ignore version if appname is null', function () { + expect(uut.userDataDir(null, null, '3.1')).to.equal( + '/Users/fake-home/Library/Application Support'); + }); + }); + + describe('userConfigDir', function () { + it('should default to ~/Library/Application Support', function () { + expect(uut.userConfigDir()).to.equal( + '/Users/fake-home/Library/Application Support'); + }); + it('should include appname', function () { + expect(uut.userConfigDir('someApp')).to.equal( + '/Users/fake-home/Library/Application Support/someApp'); + }); + it('should include version', function () { + expect(uut.userConfigDir('someApp', null, '3.1')).to.equal( + '/Users/fake-home/Library/Application Support/someApp/3.1'); + }); + it('should ignore version if appname is null', function () { + expect(uut.userConfigDir(null, null, '3.1')).to.equal( + '/Users/fake-home/Library/Application Support'); + }); + }); + + describe('userCacheDir', function () { + it('should default to ~/Library/Caches', function () { + expect(uut.userCacheDir()).to.equal( + '/Users/fake-home/Library/Caches'); + }); + it('should include appname', function () { + expect(uut.userCacheDir('someApp')).to.equal( + '/Users/fake-home/Library/Caches/someApp'); + }); + it('should include version', function () { + expect(uut.userCacheDir('someApp', null, '3.1')).to.equal( + '/Users/fake-home/Library/Caches/someApp/3.1'); + }); + it('should ignore version if appname is null', function () { + expect(uut.userCacheDir(null, null, '3.1')).to.equal( + '/Users/fake-home/Library/Caches'); + }); + }); + + describe('siteDataDir', function () { + it('should default to /Library/Application Support', function () { + expect(uut.siteDataDir()).to.equal( + '/Library/Application Support'); + }); + it('should include appname', function () { + expect(uut.siteDataDir('someApp')).to.equal( + '/Library/Application Support/someApp'); + }); + it('should include version', function () { + expect(uut.siteDataDir('someApp', null, '3.1')).to.equal( + '/Library/Application Support/someApp/3.1'); + }); + it('should ignore version if appname is null', function () { + expect(uut.siteDataDir(null, null, '3.1')).to.equal( + '/Library/Application Support'); + }); + it('should handle multipath = true', function () { + expect(uut.siteDataDir('someApp', null, '3.1', true)).to.deep.equal( + ['/Library/Application Support/someApp/3.1']); + }); + }); + + describe('siteConfigDir', function () { + it('should default to /Library/Application Support', function () { + expect(uut.siteConfigDir()).to.equal( + '/Library/Application Support'); + }); + it('should include appname', function () { + expect(uut.siteConfigDir('someApp')).to.equal( + '/Library/Application Support/someApp'); + }); + it('should include version', function () { + expect(uut.siteConfigDir('someApp', null, '3.1')).to.equal( + '/Library/Application Support/someApp/3.1'); + }); + it('should ignore version if appname is null', function () { + expect(uut.siteConfigDir(null, null, '3.1')).to.equal( + '/Library/Application Support'); + }); + it('should handle multipath = true', function () { + expect(uut.siteConfigDir('someApp', null, '3.1', true)).to.deep.equal( + ['/Library/Application Support/someApp/3.1']); + }); + }); + + describe('userLogDir', function () { + it('should default to ~/Library/Logs', function () { + expect(uut.userLogDir()).to.equal( + '/Users/fake-home/Library/Logs'); + }); + it('should include appname', function () { + expect(uut.userLogDir('someApp')).to.equal( + '/Users/fake-home/Library/Logs/someApp'); + }); + it('should include version', function () { + expect(uut.userLogDir('someApp', null, '3.1')).to.equal( + '/Users/fake-home/Library/Logs/someApp/3.1'); + }); + it('should ignore version if appname is null', function () { + expect(uut.userLogDir(null, null, '3.1')).to.equal( + '/Users/fake-home/Library/Logs'); + }); + }); +}); diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 0000000..9e83989 --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1,3 @@ +--ui bdd +--reporter spec +--check-leaks diff --git a/test/windows.spec.js b/test/windows.spec.js new file mode 100644 index 0000000..0ed27cb --- /dev/null +++ b/test/windows.spec.js @@ -0,0 +1,2 @@ +// Copyright (c) 2014. David M. Lee, II. +'use strict'; diff --git a/test/xdg.spec.js b/test/xdg.spec.js new file mode 100644 index 0000000..a660480 --- /dev/null +++ b/test/xdg.spec.js @@ -0,0 +1,299 @@ +// Copyright (c) 2014. David M. Lee, II. +/* global before, after, describe, it */ +/* jshint expr:true */ +'use strict'; + +var appdirs = require('..'), + chai = require('chai'), + expect = chai.expect; + +chai.Assertion.includeStack = true; + +describe('AppDirs on Mac', function () { + var envOrig, + uut = appdirs.xdg; + + before(function () { + envOrig = { + XDG_DATA_HOME: process.env.XDG_DATA_HOME, + XDG_CONFIG_HOME: process.env.XDG_CONFIG_HOME, + XDG_DATA_DIRS: process.env.XDG_DATA_DIRS, + HOME: process.env.HOME + }; + process.env.HOME = '/home/fake-home'; + delete process.env.XDG_DATA_HOME; + delete process.env.XDG_CONFIG_HOME; + delete process.env.XDG_DATA_DIRS; + }); + + after(function () { + process.env.HOME = envOrig.HOME; + if (envOrig.XDG_DATA_HOME !== undefined) { + process.env.XDG_DATA_HOME = envOrig.XDG_DATA_HOME; + } + if (envOrig.XDG_CONFIG_HOME !== undefined) { + process.env.XDG_CONFIG_HOME = envOrig.XDG_CONFIG_HOME; + } + if (envOrig.XDG_DATA_DIRS !== undefined) { + process.env.XDG_DATA_DIRS = envOrig.XDG_DATA_DIRS; + } + }); + + describe('userDataDir', function () { + it('should default to ~/.local/share', function () { + expect(uut.userDataDir()).to.equal( + '/home/fake-home/.local/share'); + }); + it('should include appname', function () { + expect(uut.userDataDir('someApp')).to.equal( + '/home/fake-home/.local/share/someApp'); + }); + it('should include version', function () { + expect(uut.userDataDir('someApp', null, '3.1')).to.equal( + '/home/fake-home/.local/share/someApp/3.1'); + }); + it('should ignore version if appname is null', function () { + expect(uut.userDataDir(null, null, '3.1')).to.equal( + '/home/fake-home/.local/share'); + }); + }); + + describe('userConfigDir', function () { + it('should default to ~/.config', function () { + expect(uut.userConfigDir()).to.equal( + '/home/fake-home/.config'); + }); + it('should include appname', function () { + expect(uut.userConfigDir('someApp')).to.equal( + '/home/fake-home/.config/someApp'); + }); + it('should include version', function () { + expect(uut.userConfigDir('someApp', null, '3.1')).to.equal( + '/home/fake-home/.config/someApp/3.1'); + }); + it('should ignore version if appname is null', function () { + expect(uut.userConfigDir(null, null, '3.1')).to.equal( + '/home/fake-home/.config'); + }); + }); + + describe('userCacheDir', function () { + it('should default to ~/.cache', function () { + expect(uut.userCacheDir()).to.equal( + '/home/fake-home/.cache'); + }); + it('should include appname', function () { + expect(uut.userCacheDir('someApp')).to.equal( + '/home/fake-home/.cache/someApp'); + }); + it('should include version', function () { + expect(uut.userCacheDir('someApp', null, '3.1')).to.equal( + '/home/fake-home/.cache/someApp/3.1'); + }); + it('should ignore version if appname is null', function () { + expect(uut.userCacheDir(null, null, '3.1')).to.equal( + '/home/fake-home/.cache'); + }); + }); + + describe('siteDataDir', function () { + it('should default to /usr/local/share', function () { + expect(uut.siteDataDir()).to.equal( + '/usr/local/share'); + }); + it('should include appname', function () { + expect(uut.siteDataDir('someApp')).to.equal( + '/usr/local/share/someApp'); + }); + it('should include version', function () { + expect(uut.siteDataDir('someApp', null, '3.1')).to.equal( + '/usr/local/share/someApp/3.1'); + }); + it('should ignore version if appname is null', function () { + expect(uut.siteDataDir(null, null, '3.1')).to.equal( + '/usr/local/share'); + }); + it('should handle multipath = true', function () { + expect(uut.siteDataDir('someApp', null, '3.1', true)).to.deep.equal( + ['/usr/local/share/someApp/3.1', '/usr/share/someApp/3.1']); + }); + }); + + describe('siteConfigDir', function () { + it('should default to /etc/xdg', function () { + expect(uut.siteConfigDir()).to.equal( + '/etc/xdg'); + }); + it('should include appname', function () { + expect(uut.siteConfigDir('someApp')).to.equal( + '/etc/xdg/someApp'); + }); + it('should include version', function () { + expect(uut.siteConfigDir('someApp', null, '3.1')).to.equal( + '/etc/xdg/someApp/3.1'); + }); + it('should ignore version if appname is null', function () { + expect(uut.siteConfigDir(null, null, '3.1')).to.equal( + '/etc/xdg'); + }); + it('should handle multipath = true', function () { + expect(uut.siteConfigDir('someApp', null, '3.1', true)).to.deep.equal( + ['/etc/xdg/someApp/3.1']); + }); + }); + + describe('userLogDir', function () { + it('should default to ~/.cache/log', function () { + expect(uut.userLogDir()).to.equal( + '/home/fake-home/.cache/log'); + }); + it('should include appname', function () { + expect(uut.userLogDir('someApp')).to.equal( + '/home/fake-home/.cache/someApp/log'); + }); + it('should include version', function () { + expect(uut.userLogDir('someApp', null, '3.1')).to.equal( + '/home/fake-home/.cache/someApp/3.1/log'); + }); + it('should ignore version if appname is null', function () { + expect(uut.userLogDir(null, null, '3.1')).to.equal( + '/home/fake-home/.cache/log'); + }); + }); + + describe('when XDG_DATA_HOME is set', function () { + before(function () { + process.env.XDG_DATA_HOME = '/xdg/data/home'; + }); + after(function () { + delete process.env.XDG_DATA_HOME; + }); + + describe('userDataDir', function () { + it('should use XDG_DATA_HOME', function () { + expect(uut.userDataDir('someApp', null, '3.1')).to.equal( + '/xdg/data/home/someApp/3.1'); + }); + }); + }); + + describe('when XDG_CONFIG_HOME is set', function () { + before(function () { + process.env.XDG_CONFIG_HOME = '/xdg/config/home'; + }); + after(function () { + delete process.env.XDG_CONFIG_HOME; + }); + + describe('userConfigDir', function () { + it('should use XDG_CONFIG_HOME', function () { + expect(uut.userConfigDir('someApp', null, '3.1')).to.equal( + '/xdg/config/home/someApp/3.1'); + }); + }); + }); + + describe('when XDG_CACHE_HOME is set', function () { + before(function () { + process.env.XDG_CACHE_HOME = '/xdg/cache/home'; + }); + after(function () { + delete process.env.XDG_CACHE_HOME; + }); + + describe('userCacheDir', function () { + it('should use XDG_CACHE_HOME', function () { + expect(uut.userCacheDir('someApp', null, '3.1')).to.equal( + '/xdg/cache/home/someApp/3.1'); + }); + }); + }); + + describe('when XDG_DATA_DIRS is set', function () { + describe('to single directory', function () { + before(function () { + process.env.XDG_DATA_DIRS = '/xdg/data/dir'; + }); + after(function () { + delete process.env.XDG_DATA_DIRS; + }); + + describe('siteDataDir', function () { + it('should return single path by default', function () { + expect(uut.siteDataDir('someApp', null, '3.1')).to.equal( + '/xdg/data/dir/someApp/3.1'); + }); + + it('should handle multipath = true', function () { + expect(uut.siteDataDir('someApp', null, '3.1', true)).to.deep.equal( + ['/xdg/data/dir/someApp/3.1']); + }); + }); + }); + + describe('to multiple directories', function () { + before(function () { + process.env.XDG_DATA_DIRS = '/xdg/data/dir1:/xdg/data/dir2'; + }); + after(function () { + delete process.env.XDG_DATA_DIRS; + }); + + describe('siteDataDir', function () { + it('should return single path by default', function () { + expect(uut.siteDataDir('someApp', null, '3.1')).to.equal( + '/xdg/data/dir1/someApp/3.1'); + }); + + it('should handle multipath = true', function () { + expect(uut.siteDataDir('someApp', null, '3.1', true)).to.deep.equal( + ['/xdg/data/dir1/someApp/3.1', '/xdg/data/dir2/someApp/3.1']); + }); + }); + }); + }); + + describe('when XDG_CONFIG_DIRS is set', function () { + describe('to single directory', function () { + before(function () { + process.env.XDG_CONFIG_DIRS = '/xdg/config/dir'; + }); + after(function () { + delete process.env.XDG_CONFIG_DIRS; + }); + + describe('siteConfigDir', function () { + it('should return single path by default', function () { + expect(uut.siteConfigDir('someApp', null, '3.1')).to.equal( + '/xdg/config/dir/someApp/3.1'); + }); + + it('should handle multipath = true', function () { + expect(uut.siteConfigDir('someApp', null, '3.1', true)).to.deep.equal( + ['/xdg/config/dir/someApp/3.1']); + }); + }); + }); + + describe('to multiple directories', function () { + before(function () { + process.env.XDG_CONFIG_DIRS = '/xdg/config/dir1:/xdg/config/dir2'; + }); + after(function () { + delete process.env.XDG_CONFIG_DIRS; + }); + describe('siteConfigDir', function () { + it('should return single path by default', function () { + expect(uut.siteConfigDir('someApp', null, '3.1')).to.equal( + '/xdg/config/dir1/someApp/3.1'); + }); + + it('should handle multipath = true', function () { + expect(uut.siteConfigDir('someApp', null, '3.1', true)).to.deep.equal( + ['/xdg/config/dir1/someApp/3.1', '/xdg/config/dir2/someApp/3.1']); + + }); + }); + }); + }); +});