[Pkg-javascript-commits] [node-depd] 01/02: Imported Upstream version 0.3.0
Andrew Kelley
andrewrk-guest at moszumanska.debian.org
Sat Jun 28 15:49:14 UTC 2014
This is an automated email from the git hooks/post-receive script.
andrewrk-guest pushed a commit to branch master
in repository node-depd.
commit 95723d9e5133278301776be2bab237b64d2e35c5
Author: Andrew Kelley <superjoe30 at gmail.com>
Date: Sat Jun 28 15:43:37 2014 +0000
Imported Upstream version 0.3.0
---
.gitignore | 3 +
.npmignore | 4 +
.travis.yml | 11 +
History.md | 27 +++
LICENSE | 22 ++
Readme.md | 249 +++++++++++++++++++++++
files/message.png | Bin 0 -> 2733 bytes
index.js | 452 +++++++++++++++++++++++++++++++++++++++++
package.json | 25 +++
test/fixtures/cool-lib.js | 11 +
test/fixtures/multi-lib.js | 11 +
test/fixtures/my-lib.js | 64 ++++++
test/fixtures/new-lib.js | 6 +
test/fixtures/old-lib.js | 11 +
test/test.js | 495 +++++++++++++++++++++++++++++++++++++++++++++
15 files changed, 1391 insertions(+)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..3cd27af
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+coverage/
+node_modules/
+npm-debug.log
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..0c7e391
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,4 @@
+coverage/
+files/
+test/
+.travis.yml
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..1ff243c
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,11 @@
+language: node_js
+node_js:
+ - "0.8"
+ - "0.10"
+ - "0.11"
+matrix:
+ allow_failures:
+ - node_js: "0.11"
+ fast_finish: true
+script: "npm run-script test-travis"
+after_script: "npm install coveralls at 2.10.0 && cat ./coverage/lcov.info | coveralls"
diff --git a/History.md b/History.md
new file mode 100644
index 0000000..b9d1c6d
--- /dev/null
+++ b/History.md
@@ -0,0 +1,27 @@
+0.3.0 / 2014-06-16
+==================
+
+ * Add `NO_DEPRECATION` environment variable
+
+0.2.0 / 2014-06-15
+==================
+
+ * Add `deprecate.property(obj, prop, message)`
+ * Remove `supports-color` dependency for node.js 0.8
+
+0.1.0 / 2014-06-15
+==================
+
+ * Add `deprecate.function(fn, message)`
+ * Add `process.on('deprecation', fn)` emitter
+ * Automatically generate message when omitted from `deprecate()`
+
+0.0.1 / 2014-06-15
+==================
+
+ * Fix warning for dynamic calls at singe call site
+
+0.0.0 / 2014-06-15
+==================
+
+ * Initial implementation
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..b7dce6c
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2014 Douglas Christopher Wilson
+
+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..872a8b4
--- /dev/null
+++ b/Readme.md
@@ -0,0 +1,249 @@
+# depd
+
+[](http://badge.fury.io/js/depd)
+[](https://travis-ci.org/dougwilson/nodejs-depd)
+[](https://coveralls.io/r/dougwilson/nodejs-depd)
+
+Deprecate all the things
+
+> With great modules comes great responsibility; mark things deprecated!
+
+## Install
+
+```sh
+$ npm install depd
+```
+
+## API
+
+```js
+var depd = require('depd')
+var deprecate = depd('my-module')
+```
+
+This library allows you to display deprecation messages to your users.
+This library goes above and beyond with deprecation warnings by
+introspecting the call stack (but only the bits that it is interested
+in).
+
+Instead of just warning on the first invocation of a deprecated
+function and never again, this module will warn on the first invocation
+of a deprecated function per unique call site, making it ideal to alert
+users of all deprecated uses across the code base, rather than just
+whatever happens to execute first.
+
+The deprecation warnings from this module also include the file and line
+information for the call into the module that the deprecated function was
+in.
+
+### depd(namespace)
+
+Create a new deprecate function that uses the given namespace name in the
+messages and will display the call site prior to the stack entering the
+file this function was called from. It is highly suggested you use the
+name of your module as the namespace.
+
+### deprecate(message)
+
+Call this function from deprecated code to display a deprecation message.
+This message will appear once per unique caller site. Caller site is the
+first call site in the stack in a different file from the caller of this
+function.
+
+If the message is omitted, a message is generated for you based on the site
+of the `deprecate()` call and will display the name of the function called,
+similar to the name displayed in a stack trace.
+
+### deprecate.function(fn, message)
+
+Call this function to wrap a given function in a deprecation message on any
+call to the function. An optional message can be supplied to provide a custom
+message.
+
+### deprecate.property(obj, prop, message)
+
+Call this function to wrap a given property on object in a deprecation message
+on any accessing or setting of the property. An optional message can be supplied
+to provide a custom message.
+
+The method must be called on the object where the property belongs (not
+inherited from the prototype).
+
+If the property is a data descriptor, it will be converted to an accessor
+descriptor in order to display the deprecation message.
+
+### process.on('deprecation', fn)
+
+This module will allow easy capturing of deprecation errors by emitting the
+errors as the type "deprecation" on the global `process`. If there are no
+listeners for this type, the errors are written to STDERR as normal, but if
+there are any listeners, nothing will be written to STDERR and instead only
+emitted. From there, you can write the errors in a different format or to a
+logging source.
+
+The error represents the deprecation and is emitted only once with the same
+rules as writing to STDERR. The error has the following properties:
+
+ - `message` - This is the message given by the library
+ - `name` - This is always `'DeprecationError'`
+ - `namespace` - This is the namespace the deprecation came from
+ - `stack` - This is the stack of the call to the deprecated thing
+
+Example `error.stack` output:
+
+```
+DeprecationError: my-cool-module deprecated oldfunction
+ at Object.<anonymous> ([eval]-wrapper:6:22)
+ at Module._compile (module.js:456:26)
+ at evalScript (node.js:532:25)
+ at startup (node.js:80:7)
+ at node.js:902:3
+```
+
+### process.env.NO_DEPRECATION
+
+As a user of modules that are deprecated, the environment variable `NO_DEPRECATION`
+is provided as a quick solution to silencing deprecation warnings from being
+output. The format of this is similar to that of `DEBUG`:
+
+```sh
+$ NO_DEPRECATION=my-module,othermod node app.js
+```
+
+This will suppress deprecations from being output for "my-module" and "othermod".
+The value is a list of comma-separated namespaces. To suppress every warning
+across all namespaces, use the value `*` for a namespace.
+
+**NOTE** This will not suppress the deperecations given to any "deprecation"
+event listeners, just the output to STDERR.
+
+## Display
+
+
+
+When a user calls a function in your library that you mark deprecated, they
+will see the following written to STDERR (in the given colors, similar colors
+and layout to the `debug` module):
+
+```
+bright cyan bright yellow
+| | grey cyan
+| | | |
+▼ ▼ ▼ ▼
+my-cool-module deprecated oldfunction [eval]-wrapper:6:22
+▲ ▲ ▲ ▲
+| | | |
+namespace | | location of mycoolmod.oldfunction() call
+ | deprecation message
+ the word "deprecated"
+```
+
+If the user redirects their STDERR to a file or somewhere that does not support
+colors, they see (similar layout to the `debug` module):
+
+```
+Sun, 15 Jun 2014 05:21:37 GMT my-cool-module deprecated oldfunction at [eval]-wrapper:6:22
+▲ ▲ ▲ ▲ ▲
+| | | | |
+timestamp of message namespace | | location of mycoolmod.oldfunction() call
+ | deprecation message
+ the word "deprecated"
+```
+
+## Examples
+
+### Deprecating all calls to a function
+
+This will display a deprecated message about "oldfunction" being deprecated
+from "my-module" on STDERR.
+
+```js
+var deprecate = require('depd')('my-cool-module')
+
+// message automatically derived from function name
+// Object.oldfunction
+exports.oldfunction = deprecate.function(function oldfunction() {
+ // all calls to function are deprecated
+})
+
+// specific message
+exports.oldfunction = deprecate.function(function () {
+ // all calls to function are deprecated
+}, 'oldfunction')
+```
+
+### Conditionally deprecating a function call
+
+This will display a deprecated message about "weirdfunction" being deprecated
+from "my-module" on STDERR when called with less than 2 arguments.
+
+```js
+var deprecate = require('depd')('my-cool-module')
+
+exports.weirdfunction = function () {
+ if (arguments.length < 2) {
+ // calls with 0 or 1 args are deprecated
+ deprecate('weirdfunction args < 2')
+ }
+}
+```
+
+When calling `deprecate` as a function, the warning is counted per call site
+within your own module, so you can display different deprecations depending
+on different situations and the users will still get all the warnings:
+
+```js
+var deprecate = require('depd')('my-cool-module')
+
+exports.weirdfunction = function () {
+ if (arguments.length < 2) {
+ // calls with 0 or 1 args are deprecated
+ deprecate('weirdfunction args < 2')
+ } else if (typeof arguments[0] !== 'string') {
+ // calls with non-string first argument are deprecated
+ deprecate('weirdfunction non-string first arg')
+ }
+}
+```
+
+### Deprecating property access
+
+This will display a deprecated message about "oldprop" being deprecated
+from "my-module" on STDERR when accessed. A deprecation will be displayed
+when setting the value and when getting the value.
+
+```js
+var deprecate = require('depd')('my-cool-module')
+
+exports.oldprop = 'something'
+
+// message automatically derives from property name
+deprecate.property(exports, 'oldprop')
+
+// explicit message
+deprecate.property(exports, 'oldprop', 'oldprop >= 0.10')
+```
+
+## License
+
+The MIT License (MIT)
+
+Copyright (c) 2014 Douglas Christopher Wilson
+
+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/files/message.png b/files/message.png
new file mode 100644
index 0000000..21dc881
Binary files /dev/null and b/files/message.png differ
diff --git a/index.js b/index.js
new file mode 100644
index 0000000..f42aa07
--- /dev/null
+++ b/index.js
@@ -0,0 +1,452 @@
+/*!
+ * depd
+ * Copyright(c) 2014 Douglas Christopher Wilson
+ * MIT Licensed
+ */
+
+/**
+ * Module dependencies.
+ */
+
+var EventEmitter = require('events').EventEmitter
+var relative = require('path').relative
+
+/**
+ * Module exports.
+ */
+
+module.exports = depd
+
+/**
+ * Get the path to base files on.
+ */
+
+var basePath = process.cwd()
+
+/**
+ * Get listener count on event emitter.
+ */
+
+/*istanbul ignore next*/
+var eventListenerCount = EventEmitter.listenerCount
+ || function (emitter, type) { return emitter.listeners(type).length }
+
+/**
+ * Convert a data descriptor to accessor descriptor.
+ */
+
+function convertDataDescriptorToAccessor(obj, prop, message) {
+ var descriptor = Object.getOwnPropertyDescriptor(obj, prop)
+ var value = descriptor.value
+
+ descriptor.get = function getter() { return value }
+
+ if (descriptor.writable) {
+ descriptor.set = function setter(val) { return value = val }
+ }
+
+ delete descriptor.value
+ delete descriptor.writable
+
+ Object.defineProperty(obj, prop, descriptor)
+
+ return descriptor
+}
+
+/**
+ * Create arguments string to keep arity.
+ */
+
+function createArgumentsString(arity) {
+ var str = ''
+
+ for (var i = 0; i < arity; i++) {
+ str += ', arg' + i
+ }
+
+ return str.substr(2)
+}
+
+/**
+ * Create stack string from stack.
+ */
+
+function createStackString(stack) {
+ var str = this.name + ': ' + this.namespace
+
+ if (this.message) {
+ str += ' deprecated ' + this.message
+ }
+
+ for (var i = 0; i < stack.length; i++) {
+ str += '\n at ' + stack[i].toString()
+ }
+
+ return str
+}
+
+/**
+ * Create deprecate for namespace in caller.
+ */
+
+function depd(namespace) {
+ if (!namespace) {
+ throw new TypeError('argument namespace is required')
+ }
+
+ var stack = getStack()
+ var site = callSiteLocation(stack[1])
+ var file = site[0]
+
+ function deprecate(message) {
+ // call to self as log
+ log.call(deprecate, message)
+ }
+
+ deprecate._file = file
+ deprecate._ignored = isignored(namespace)
+ deprecate._namespace = namespace
+ deprecate._warned = Object.create(null)
+
+ deprecate.function = wrapfunction
+ deprecate.property = wrapproperty
+
+ return deprecate
+}
+
+/**
+ * Determine if namespace is ignored.
+ */
+
+function isignored(namespace) {
+ var str = process.env.NO_DEPRECATION || ''
+ var val = str.split(/[ ,]+/)
+
+ namespace = String(namespace).toLowerCase()
+
+ for (var i = 0 ; i < val.length; i++) {
+ if (!(str = val[i])) continue;
+
+ // namespace ignored
+ if (str === '*' || str.toLowerCase() === namespace) {
+ return true
+ }
+ }
+
+ return false
+}
+
+/**
+ * Display deprecation message.
+ */
+
+function log(message, site) {
+ var haslisteners = eventListenerCount(process, 'deprecation') !== 0
+
+ // abort early if no destination
+ if (!haslisteners && this._ignored) {
+ return
+ }
+
+ var caller
+ var callSite
+ var i = 0
+ var seen = false
+ var stack = getStack()
+ var file = this._file
+
+ if (site) {
+ // provided site
+ callSite = callSiteLocation(stack[1])
+ callSite.name = site.name
+ file = callSite[0]
+ } else {
+ // get call site
+ i = 2
+ site = callSiteLocation(stack[i])
+ callSite = site
+ }
+
+ // get caller of deprecated thing in relation to file
+ for (; i < stack.length; i++) {
+ caller = callSiteLocation(stack[i])
+
+ if (caller[0] === file) {
+ seen = true
+ } else if (seen) {
+ break
+ }
+ }
+
+ var key = caller
+ ? site.join(':') + '__' + caller.join(':')
+ : undefined
+
+ if (key !== undefined && key in this._warned) {
+ // already warned
+ return
+ }
+
+ this._warned[key] = true
+
+ // generate automatic message from call site
+ if (!message) {
+ message = callSite === site || !callSite.name
+ ? defaultMessage(site)
+ : defaultMessage(callSite)
+ }
+
+ // emit deprecation if listeners exist
+ if (haslisteners) {
+ var err = DeprecationError(this._namespace, message, stack.slice(i))
+ process.emit('deprecation', err)
+ return
+ }
+
+ // format and write message
+ var format = process.stderr.isTTY
+ ? formatColor
+ : formatPlain
+ var msg = format.call(this, message, caller)
+ process.stderr.write(msg + '\n', 'utf8')
+
+ return
+}
+
+/**
+ * Get call site location as array.
+ */
+
+function callSiteLocation(callSite) {
+ var file = callSite.getFileName() || '<anonymous>'
+ var line = callSite.getLineNumber()
+ var colm = callSite.getColumnNumber()
+
+ if (callSite.isEval()) {
+ file = callSite.getEvalOrigin() + ', ' + file
+ }
+
+ var site = [file, line, colm]
+
+ site.callSite = callSite
+ site.name = callSite.getFunctionName()
+
+ return site
+}
+
+/**
+ * Generate a default message from the site.
+ */
+
+function defaultMessage(site) {
+ var callSite = site.callSite
+ var funcName = site.name
+
+ // make useful anonymous name
+ if (!funcName) {
+ funcName = '<anonymous@' + formatLocation(site) + '>'
+ }
+
+ return callSite.getMethodName()
+ ? callSite.getTypeName() + '.' + funcName
+ : funcName
+}
+
+/**
+ * Format deprecation message without color.
+ */
+
+function formatPlain(msg, caller) {
+ var timestamp = new Date().toUTCString()
+
+ var formatted = timestamp
+ + ' ' + this._namespace
+ + ' deprecated ' + msg
+
+ if (caller) {
+ formatted += ' at ' + formatLocation(caller)
+ }
+
+ return formatted
+}
+
+/**
+ * Format deprecation message with color.
+ */
+
+function formatColor(msg, caller) {
+ var formatted = '\x1b[36;1m' + this._namespace + '\x1b[22;39m' // bold cyan
+ + ' \x1b[33;1mdeprecated\x1b[22;39m' // bold yellow
+ + ' \x1b[90m' + msg + '\x1b[39m' // grey
+
+ if (caller) {
+ formatted += ' \x1b[36m' + formatLocation(caller) + '\x1b[39m' // cyan
+ }
+
+ return formatted
+}
+
+/**
+ * Format call site location.
+ */
+
+function formatLocation(callSite) {
+ return relative(basePath, callSite[0])
+ + ':' + callSite[1]
+ + ':' + callSite[2]
+}
+
+/**
+ * Get the stack as array of call sites.
+ */
+
+function getStack() {
+ var obj = {}
+ var prep = Error.prepareStackTrace
+
+ Error.prepareStackTrace = prepareObjectStackTrace
+ Error.captureStackTrace(obj, getStack)
+
+ var stack = obj.stack
+
+ Error.prepareStackTrace = prep
+
+ return stack
+}
+
+/**
+ * Capture call site stack from v8.
+ */
+
+function prepareObjectStackTrace(obj, stack) {
+ return stack
+}
+
+/**
+ * Return a wrapped function in a deprecation message.
+ */
+
+function wrapfunction(fn, message) {
+ if (typeof fn !== 'function') {
+ throw new TypeError('argument fn must be a function')
+ }
+
+ var args = createArgumentsString(fn.length)
+ var deprecate = this
+ var stack = getStack()
+ var site = callSiteLocation(stack[1])
+
+ site.name = fn.name
+
+ var deprecatedfn = eval('(function (' + args + ') {\n'
+ + 'log.call(deprecate, message, site)\n'
+ + 'return fn.apply(this, arguments)\n'
+ + '})')
+
+ return deprecatedfn
+}
+
+/**
+ * Wrap property in a deprecation message.
+ */
+
+function wrapproperty(obj, prop, message) {
+ if (!obj || typeof obj !== 'object') {
+ throw new TypeError('argument obj must be object')
+ }
+
+ var descriptor = Object.getOwnPropertyDescriptor(obj, prop)
+
+ if (!descriptor) {
+ throw new TypeError('must call property on owner object')
+ }
+
+ if (!descriptor.configurable) {
+ throw new TypeError('property must be configurable')
+ }
+
+ var deprecate = this
+ var stack = getStack()
+ var site = callSiteLocation(stack[1])
+
+ // set site name
+ site.name = prop
+
+ // convert data descriptor
+ if ('value' in descriptor) {
+ descriptor = convertDataDescriptorToAccessor(obj, prop, message)
+ }
+
+ var get = descriptor.get
+ var set = descriptor.set
+
+ // wrap getter
+ if (typeof get === 'function') {
+ descriptor.get = function getter() {
+ log.call(deprecate, message, site)
+ return get.apply(this, arguments)
+ }
+ }
+
+ // wrap setter
+ if (typeof set === 'function') {
+ descriptor.set = function setter() {
+ log.call(deprecate, message, site)
+ return set.apply(this, arguments)
+ }
+ }
+
+ Object.defineProperty(obj, prop, descriptor)
+}
+
+/**
+ * Create DeprecationError for deprecation
+ */
+
+function DeprecationError(namespace, message, stack) {
+ var error = new Error()
+ var stackString
+
+ Object.defineProperty(error, 'constructor', {
+ value: DeprecationError
+ })
+
+ Object.defineProperty(error, 'message', {
+ configurable: true,
+ enumerable: false,
+ value: message,
+ writable: true
+ })
+
+ Object.defineProperty(error, 'name', {
+ enumerable: false,
+ configurable: true,
+ value: 'DeprecationError',
+ writable: true
+ })
+
+ Object.defineProperty(error, 'namespace', {
+ configurable: true,
+ enumerable: false,
+ value: namespace,
+ writable: true
+ })
+
+ Object.defineProperty(error, 'stack', {
+ configurable: true,
+ enumerable: false,
+ get: function () {
+ if (stackString !== undefined) {
+ return stackString
+ }
+
+ // prepare stack trace
+ return stackString = createStackString.call(this, stack)
+ },
+ set: function setter(val) {
+ stackString = val
+ }
+ })
+
+ return error
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..bc62cf5
--- /dev/null
+++ b/package.json
@@ -0,0 +1,25 @@
+{
+ "name": "depd",
+ "description": "Deprecate all the things",
+ "version": "0.3.0",
+ "author": "Douglas Christopher Wilson <doug at somethingdoug.com>",
+ "license": "MIT",
+ "keywords": [
+ "deprecate",
+ "deprecated"
+ ],
+ "repository": "dougwilson/nodejs-depd",
+ "devDependencies": {
+ "istanbul": "0.2.10",
+ "mocha": "~1.20.1",
+ "should": "~4.0.4"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ },
+ "scripts": {
+ "test": "mocha --reporter spec --bail --require should test/",
+ "test-cov": "istanbul cover node_modules/mocha/bin/_mocha -- --reporter dot --require should test/",
+ "test-travis": "istanbul cover node_modules/mocha/bin/_mocha --report lcovonly -- --reporter spec --require should test/"
+ }
+}
diff --git a/test/fixtures/cool-lib.js b/test/fixtures/cool-lib.js
new file mode 100644
index 0000000..e8ed86b
--- /dev/null
+++ b/test/fixtures/cool-lib.js
@@ -0,0 +1,11 @@
+
+var deprecate1 = require('../..')('cool-lib')
+var deprecate2 = require('../..')('neat-lib')
+
+exports.cool = function () {
+ deprecate1('cool')
+}
+
+exports.neat = function () {
+ deprecate2('neat')
+}
diff --git a/test/fixtures/multi-lib.js b/test/fixtures/multi-lib.js
new file mode 100644
index 0000000..7129761
--- /dev/null
+++ b/test/fixtures/multi-lib.js
@@ -0,0 +1,11 @@
+
+var deprecate1 = require('../..')('multi-lib')
+var deprecate2 = require('../..')('multi-lib-other')
+
+exports.old = function () {
+ deprecate1('old')
+}
+
+exports.old2 = function () {
+ deprecate2('old2')
+}
diff --git a/test/fixtures/my-lib.js b/test/fixtures/my-lib.js
new file mode 100644
index 0000000..fa096cc
--- /dev/null
+++ b/test/fixtures/my-lib.js
@@ -0,0 +1,64 @@
+
+var deprecate = require('../..')('my-lib')
+
+exports.old = function () {
+ deprecate('old')
+}
+
+exports.old2 = function () {
+ deprecate('old2')
+}
+
+exports.oldfn = deprecate.function(fn, 'oldfn')
+
+exports.oldfnauto = deprecate.function(fn)
+
+exports.oldfnautoanon = deprecate.function(function () {})
+
+exports.propa = 'thingie'
+exports.propauto = 'thingie'
+
+Object.defineProperty(exports, 'propget', {
+ configurable: true,
+ value: 'thingie',
+ writable: false
+})
+
+Object.defineProperty(exports, 'propdyn', {
+ configurable: true,
+ get: function () { return 'thingie' },
+ set: function () {}
+})
+
+Object.defineProperty(exports, 'propgetter', {
+ configurable: true,
+ get: function () { return 'thingie' }
+})
+
+Object.defineProperty(exports, 'propsetter', {
+ configurable: true,
+ set: function () {}
+})
+
+deprecate.property(exports, 'propa', 'propa gone')
+deprecate.property(exports, 'propauto')
+deprecate.property(exports, 'propdyn')
+deprecate.property(exports, 'propget')
+deprecate.property(exports, 'propgetter')
+deprecate.property(exports, 'propsetter')
+
+exports.automsg = function () {
+ deprecate()
+}
+
+exports.automsgnamed = function automsgnamed() {
+ deprecate()
+}
+
+exports.automsganon = function () {
+ (function () { deprecate() }())
+}
+
+function fn(a1, a2) {
+ return a2
+}
diff --git a/test/fixtures/new-lib.js b/test/fixtures/new-lib.js
new file mode 100644
index 0000000..f9593a1
--- /dev/null
+++ b/test/fixtures/new-lib.js
@@ -0,0 +1,6 @@
+
+var deprecate = require('../..')('new-lib')
+
+exports.old = function () {
+ deprecate('old')
+}
diff --git a/test/fixtures/old-lib.js b/test/fixtures/old-lib.js
new file mode 100644
index 0000000..fc33744
--- /dev/null
+++ b/test/fixtures/old-lib.js
@@ -0,0 +1,11 @@
+
+var deprecate1 = require('../..')('old-lib')
+var deprecate2 = require('../..')('old-lib-other')
+
+exports.old = function () {
+ deprecate1('old')
+}
+
+exports.old2 = function () {
+ deprecate2('old2')
+}
diff --git a/test/test.js b/test/test.js
new file mode 100644
index 0000000..50882d0
--- /dev/null
+++ b/test/test.js
@@ -0,0 +1,495 @@
+
+var basename = require('path').basename
+var depd = require('..')
+var mylib = require('./fixtures/my-lib')
+var should = require('should')
+
+describe('depd(namespace)', function () {
+ it('creates deprecated function', function () {
+ depd('test').should.be.a.function
+ })
+
+ it('requires namespace', function () {
+ depd.bind().should.throw(/namespace.*required/)
+ })
+})
+
+describe('deprecate(message)', function () {
+ it('should log namespace', function () {
+ function callold() { mylib.old() }
+ captureStderr(callold).should.containEql('my-lib')
+ })
+
+ it('should log deprecation', function () {
+ function callold() { mylib.old() }
+ captureStderr(callold).should.containEql('deprecate')
+ })
+
+ it('should log message', function () {
+ function callold() { mylib.old() }
+ captureStderr(callold).should.containEql('old')
+ })
+
+ it('should log call site', function () {
+ function callold() { mylib.old() }
+ var stderr = captureStderr(callold)
+ stderr.should.containEql(basename(__filename))
+ stderr.should.match(/\.js:[0-9]+:[0-9]+/)
+ })
+
+ it('should log call site within eval', function () {
+ function callold() { eval('mylib.old()') }
+ var stderr = captureStderr(callold)
+ stderr.should.containEql(basename(__filename))
+ stderr.should.containEql('<anonymous>:1:')
+ stderr.should.match(/\.js:[0-9]+:[0-9]+/)
+ })
+
+ it('should only warn once per call site', function () {
+ function callold() {
+ for (var i = 0; i < 5; i++) {
+ mylib.old() // single call site
+ process.stderr.write('invoke ' + i + '\n')
+ }
+ }
+
+ var stderr = captureStderr(callold)
+ stderr.split('deprecated').should.have.length(2)
+ stderr.split('invoke').should.have.length(6)
+ })
+
+ it('should warn for different fns on same call site', function () {
+ var prop
+
+ function callold() {
+ mylib[prop]() // call from same site
+ }
+
+ prop = 'old'
+ captureStderr(callold).should.containEql(basename(__filename))
+
+ prop = 'old2'
+ captureStderr(callold).should.containEql(basename(__filename))
+ })
+
+ it('should warn for different calls on same line', function () {
+ function callold() {
+ mylib.old(), mylib.old()
+ }
+
+ var stderr = captureStderr(callold)
+ var fileline = stderr.match(/\.js:[0-9]+:/)
+ stderr.should.containEql(basename(__filename))
+ stderr.split('deprecated').should.have.length(3)
+ stderr.split(fileline[0]).should.have.length(3)
+ })
+
+ describe('when message omitted', function () {
+ it('should generate message for method call on named function', function () {
+ function callold() { mylib.automsgnamed() }
+ var stderr = captureStderr(callold)
+ stderr.should.containEql(basename(__filename))
+ stderr.should.containEql('deprecated')
+ stderr.should.containEql(' Object.automsgnamed ')
+ })
+
+ it('should generate message for function call on named function', function () {
+ function callold() {
+ var fn = mylib.automsgnamed
+ fn()
+ }
+ var stderr = captureStderr(callold)
+ stderr.should.containEql(basename(__filename))
+ stderr.should.containEql('deprecated')
+ stderr.should.containEql(' automsgnamed ')
+ })
+
+ it('should generate message for method call on unnamed function', function () {
+ function callold() { mylib.automsg() }
+ var stderr = captureStderr(callold)
+ stderr.should.containEql(basename(__filename))
+ stderr.should.containEql('deprecated')
+ stderr.should.containEql(' Object.exports.automsg ')
+ })
+
+ it('should generate message for function call on unnamed function', function () {
+ function callold() {
+ var fn = mylib.automsg
+ fn()
+ }
+ var stderr = captureStderr(callold)
+ stderr.should.containEql(basename(__filename))
+ stderr.should.containEql('deprecated')
+ stderr.should.containEql(' exports.automsg ')
+ })
+
+ it('should generate message for function call on anonymous function', function () {
+ function callold() { mylib.automsganon() }
+ var stderr = captureStderr(callold)
+ stderr.should.containEql(basename(__filename))
+ stderr.should.containEql('deprecated')
+ stderr.should.match(/ exports\.automsganon | <anonymous@[^:]+:[0-9]+:[0-9]+> /)
+ })
+ })
+
+ describe('when output supports colors', function () {
+ var stderr
+ before(function () {
+ function callold() { mylib.old() }
+ stderr = captureStderr(callold, true)
+ })
+
+ it('should log in color', function () {
+ stderr.should.not.be.empty
+ stderr.should.containEql('\x1b[')
+ })
+
+ it('should log namespace', function () {
+ stderr.should.containEql('my-lib')
+ })
+
+ it('should log deprecation', function () {
+ stderr.should.containEql('deprecate')
+ })
+
+ it('should log message', function () {
+ stderr.should.containEql('old')
+ })
+
+ it('should log call site', function () {
+ stderr.should.containEql(basename(__filename))
+ stderr.should.match(/\.js:[0-9]+:[0-9]+/)
+ })
+ })
+
+ describe('when output does not support colors', function () {
+ var stderr
+ before(function () {
+ function callold() { mylib.old() }
+ stderr = captureStderr(callold, false)
+ })
+
+ it('should not log in color', function () {
+ stderr.should.not.be.empty
+ stderr.should.not.containEql('\x1b[')
+ })
+
+ it('should log namespace', function () {
+ stderr.should.containEql('my-lib')
+ })
+
+ it('should log timestamp', function () {
+ stderr.should.match(/\w+, \d+ \w+ \d{4} \d{2}:\d{2}:\d{2} \w{3}/)
+ })
+
+ it('should log deprecation', function () {
+ stderr.should.containEql('deprecate')
+ })
+
+ it('should log message', function () {
+ stderr.should.containEql('old')
+ })
+
+ it('should log call site', function () {
+ stderr.should.containEql(basename(__filename))
+ stderr.should.match(/\.js:[0-9]+:[0-9]+/)
+ })
+ })
+})
+
+describe('deprecate.function(fn, message)', function () {
+ it('should thrown when not given function', function () {
+ var deprecate = depd('test')
+ deprecate.function.bind(deprecate, 2).should.throw(/fn.*function/)
+ })
+
+ it('should log on call to function', function () {
+ function callold() { mylib.oldfn() }
+ captureStderr(callold).should.containEql(' oldfn ')
+ })
+
+ it('should have same arity', function () {
+ mylib.oldfn.should.have.length(2)
+ })
+
+ it('should pass arguments', function () {
+ var ret
+ function callold() { ret = mylib.oldfn(1, 2) }
+ captureStderr(callold).should.containEql(' oldfn ')
+ ret.should.equal(2)
+ })
+
+ it('should only warn once per call site', function () {
+ function callold() {
+ for (var i = 0; i < 5; i++) {
+ mylib.oldfn() // single call site
+ process.stderr.write('invoke ' + i + '\n')
+ }
+ }
+
+ var stderr = captureStderr(callold)
+ stderr.split('deprecated').should.have.length(2)
+ stderr.split('invoke').should.have.length(6)
+ })
+
+ it('should warn for different calls on same line', function () {
+ function callold() {
+ mylib.oldfn(), mylib.oldfn()
+ }
+
+ var stderr = captureStderr(callold)
+ var fileline = stderr.match(/\.js:[0-9]+:/)
+ stderr.should.containEql(basename(__filename))
+ stderr.split('deprecated').should.have.length(3)
+ stderr.split(fileline[0]).should.have.length(3)
+ })
+
+ describe('when message omitted', function () {
+ it('should generate message for method call on named function', function () {
+ function callold() { mylib.oldfnauto() }
+ var stderr = captureStderr(callold)
+ stderr.should.containEql(basename(__filename))
+ stderr.should.containEql('deprecated')
+ stderr.should.containEql(' Object.fn ')
+ stderr.should.match(/ at [^:]+test\.js:/)
+ })
+
+ it('should generate message for method call on anonymous function', function () {
+ function callold() { mylib.oldfnautoanon() }
+ var stderr = captureStderr(callold)
+ stderr.should.containEql(basename(__filename))
+ stderr.should.containEql('deprecated')
+ stderr.should.match(/ <anonymous@[^:]+my-lib\.js:[0-9]+:[0-9]+> /)
+ stderr.should.match(/ at [^:]+test\.js:/)
+ })
+ })
+})
+
+describe('deprecate.property(obj, prop, message)', function () {
+ it('should throw when given primitive', function () {
+ var deprecate = depd('test')
+ deprecate.property.bind(deprecate, 2).should.throw(/obj.*object/)
+ })
+
+ it('should throw when given missing property', function () {
+ var deprecate = depd('test')
+ var obj = {}
+ deprecate.property.bind(deprecate, obj, 'blargh').should.throw(/property.*owner/)
+ })
+
+ it('should throw when given non-configurable property', function () {
+ var deprecate = depd('test')
+ var obj = {}
+ Object.defineProperty(obj, 'thing', {value: 'thingie'})
+ deprecate.property.bind(deprecate, obj, 'thing').should.throw(/property.*configurable/)
+ })
+
+ it('should log on access to property', function () {
+ function callprop() { mylib.propa }
+ var stderr = captureStderr(callprop)
+ stderr.should.containEql(' deprecated ')
+ stderr.should.containEql(' propa gone ')
+ })
+
+ it('should log on setting property', function () {
+ var val
+ function callprop() { val = mylib.propa }
+ function setprop() { mylib.propa = 'newval' }
+ var stderr = captureStderr(setprop)
+ stderr.should.containEql(' deprecated ')
+ stderr.should.containEql(' propa gone ')
+ captureStderr(callprop).should.containEql(' deprecated ')
+ val.should.equal('newval')
+ })
+
+ it('should only warn once per call site', function () {
+ function callold() {
+ for (var i = 0; i < 5; i++) {
+ mylib.propa // single call site
+ process.stderr.write('access ' + i + '\n')
+ }
+ }
+
+ var stderr = captureStderr(callold)
+ stderr.split('deprecated').should.have.length(2)
+ stderr.split('access').should.have.length(6)
+ })
+
+ it('should warn for different accesses on same line', function () {
+ function callold() {
+ mylib.propa, mylib.propa
+ }
+
+ var stderr = captureStderr(callold)
+ var fileline = stderr.match(/\.js:[0-9]+:/)
+ stderr.should.containEql(basename(__filename))
+ stderr.split('deprecated').should.have.length(3)
+ stderr.split(fileline[0]).should.have.length(3)
+ })
+
+ describe('when value descriptor', function () {
+ it('should log on access and set', function () {
+ function callold() { mylib.propa }
+ function setold() { mylib.propa = 'val' }
+ captureStderr(callold).should.containEql(' deprecated ')
+ captureStderr(setold).should.containEql(' deprecated ')
+ })
+
+ it('should not log on set to non-writable', function () {
+ function callold() { mylib.propget }
+ function setold() { mylib.propget = 'val' }
+ captureStderr(callold).should.containEql(' deprecated ')
+ captureStderr(setold).should.be.empty
+ })
+ })
+
+ describe('when accessor descriptor', function () {
+ it('should log on access and set', function () {
+ function callold() { mylib.propdyn }
+ function setold() { mylib.propdyn = 'val' }
+ captureStderr(callold).should.containEql(' deprecated ')
+ captureStderr(setold).should.containEql(' deprecated ')
+ })
+
+ it('should not log on access when no accessor', function () {
+ function callold() { mylib.propsetter }
+ captureStderr(callold).should.be.empty
+ })
+
+ it('should not log on set when no setter', function () {
+ function callold() { mylib.propgetter = 'val' }
+ captureStderr(callold).should.be.empty
+ })
+ })
+
+ describe('when message omitted', function () {
+ it('should generate message for method call on named function', function () {
+ function callold() { mylib.propauto }
+ var stderr = captureStderr(callold)
+ stderr.should.containEql(basename(__filename))
+ stderr.should.containEql('deprecated')
+ stderr.should.containEql(' Object.propauto ')
+ stderr.should.match(/ at [^:]+test\.js:/)
+ })
+ })
+})
+
+describe('process.on(\'deprecation\', fn)', function () {
+ var error
+ var stderr
+ before(function () {
+ process.on('deprecation', ondeprecation)
+ function callold() { mylib.old() }
+ stderr = captureStderr(callold)
+ })
+ after(function () {
+ process.removeListener('deprecation', ondeprecation)
+ })
+
+ function ondeprecation(err) { error = err }
+
+ it('should not write when listener exists', function () {
+ stderr.should.be.empty
+ })
+
+ it('should emit error', function () {
+ error.should.be.ok
+ })
+
+ it('should emit DeprecationError', function () {
+ error.name.should.equal('DeprecationError')
+ })
+
+ it('should emit DeprecationError', function () {
+ error.name.should.equal('DeprecationError')
+ })
+
+ it('should emit error with message', function () {
+ error.message.should.equal('old')
+ })
+
+ it('should emit error with namespace', function () {
+ error.namespace.should.equal('my-lib')
+ })
+
+ it('should emit error with proper [[Class]]', function () {
+ Object.prototype.toString.call(error).should.equal('[object Error]')
+ })
+
+ it('should be instanceof Error', function () {
+ error.should.be.instanceof(Error)
+ })
+
+ it('should emit error with proper stack', function () {
+ var stack = error.stack.split('\n')
+ stack[0].should.equal('DeprecationError: my-lib deprecated old')
+ stack[1].should.match(/ at callold \(.+test\.js:[0-9]+:[0-9]+\)/)
+ })
+
+ it('should have writable properties', function () {
+ error.name = 'bname'
+ error.name.should.equal('bname')
+ error.message = 'bmessage'
+ error.message.should.equal('bmessage')
+ error.stack = 'bstack'
+ error.stack.should.equal('bstack')
+ })
+})
+
+describe('process.env.NO_DEPRECATION', function () {
+ var error
+ function ondeprecation(err) { error = err }
+
+ after(function () {
+ process.env.NO_DEPRECATION = ''
+ })
+
+ it('should suppress given namespace', function () {
+ process.env.NO_DEPRECATION = 'old-lib'
+ var oldlib = require('./fixtures/old-lib')
+ captureStderr(oldlib.old).should.be.empty
+ captureStderr(oldlib.old2).should.not.be.empty
+ })
+
+ it('should suppress multiple namespaces', function () {
+ process.env.NO_DEPRECATION = 'cool-lib,neat-lib'
+ var coollib = require('./fixtures/cool-lib')
+ captureStderr(coollib.cool).should.be.empty
+ captureStderr(coollib.neat).should.be.empty
+ })
+
+ it('should be case-insensitive', function () {
+ process.env.NO_DEPRECATION = 'NEW-LIB'
+ var newlib = require('./fixtures/new-lib')
+ captureStderr(newlib.old).should.be.empty
+ })
+
+ describe('when *', function () {
+ it('should suppress any namespace', function () {
+ process.env.NO_DEPRECATION = '*'
+ var multilib = require('./fixtures/multi-lib')
+ captureStderr(multilib.old).should.be.empty
+ captureStderr(multilib.old2).should.be.empty
+ })
+ })
+})
+
+function captureStderr(fn, color) {
+ var chunks = []
+ var isTTY = process.stderr.isTTY
+ var write = process.stderr.write
+
+ process.stderr.isTTY = Boolean(color)
+ process.stderr.write = function write(chunk, encoding) {
+ chunks.push(new Buffer(chunk, encoding))
+ }
+
+ try {
+ fn()
+ } finally {
+ process.stderr.isTTY = isTTY
+ process.stderr.write = write
+ }
+
+ return Buffer.concat(chunks).toString('utf8')
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-depd.git
More information about the Pkg-javascript-commits
mailing list