pax_global_header00006660000000000000000000000064135576174040014526gustar00rootroot0000000000000052 comment=45c01b70d8cdbf8f662d1b6ce5754d9838a2e5ad promise-core-1.1.3/000077500000000000000000000000001355761740400141345ustar00rootroot00000000000000promise-core-1.1.3/.editorconfig000066400000000000000000000006601355761740400166130ustar00rootroot00000000000000# EditorConfig is awesome: http://EditorConfig.org root = true [*] charset = utf-8 end_of_line = lf [*.js] indent_style = space indent_size = 4 trim_trailing_whitespace = true insert_final_newline = true [*.{json,xml}] indent_style = space indent_size = 2 trim_trailing_whitespace = true insert_final_newline = true [*.{md,txt}] indent_style = space indent_size = 4 trim_trailing_whitespace = false insert_final_newline = falsepromise-core-1.1.3/.eslintrc.json000066400000000000000000000103531355761740400167320ustar00rootroot00000000000000{ "root": true, "parser": "espree", "parserOptions": { "ecmaVersion": 5, "sourceType": "script", "ecmaFeatures": {} }, "plugins": [], "env": { "node": true }, "globals": {}, "rules": { // Possible Errors (fully reviewed 2016-07-05) "no-cond-assign": 2, "no-console": 0, "no-constant-condition": 2, "no-control-regex": 2, "no-debugger": 2, "no-dupe-args": 2, "no-dupe-keys": 2, "no-duplicate-case": 2, "no-empty": [2, { "allowEmptyCatch": false }], "no-empty-character-class": 2, "no-ex-assign": 2, "no-extra-boolean-cast": 2, "no-extra-parens": [2, "all"], "no-extra-semi": 2, "no-func-assign": 2, "no-inner-declarations": [2, "functions"], "no-invalid-regexp": 2, "no-irregular-whitespace": [2, { "skipComments": false }], "no-negated-in-lhs": 2, "no-obj-calls": 2, "no-prototype-builtins": 2, "no-regex-spaces": 2, "no-sparse-arrays": 2, "no-unexpected-multiline": 2, "no-unreachable": 2, "no-unsafe-finally": 2, "use-isnan": 2, "valid-jsdoc": 0, "valid-typeof": 2, // Best Practices "accessor-pairs": 2, "curly": [2, "multi-line"], "dot-location": [2, "property"], "eqeqeq": 2, "no-caller": 2, "no-empty-pattern": 0, // for ES6 destructuring "no-eval": 2, "no-extend-native": 2, "no-extra-bind": 2, "no-fallthrough": 2, "no-floating-decimal": 2, "no-implied-eval": 2, "no-iterator": 2, "no-labels": 2, "no-lone-blocks": 2, "no-magic-numbers": 0, "no-multi-spaces": 2, "no-multi-str": 2, "no-native-reassign": 2, "no-new": 2, "no-new-func": 2, "no-new-wrappers": 2, "no-octal": 2, "no-octal-escape": 2, "no-proto": 2, "no-redeclare": 2, "no-return-assign": [2, "except-parens"], "no-self-assign": 2, "no-self-compare": 2, "no-sequences": 2, "no-throw-literal": 2, "no-unmodified-loop-condition": 2, "no-useless-call": 2, "no-useless-escape": 2, "no-with": 2, "wrap-iife": [2, "inside"], "yoda": 2, // Strict Mode (fully reviewed 2016-07-05) "strict": [2, "safe"], // Variables (fully reviewed 2016-07-05) "init-declarations": [2, "always"], "no-catch-shadow": 0, "no-delete-var": 2, "no-label-var": 2, "no-restricted-globals": 0, "no-shadow": [2, { "builtinGlobals": false, "hoist": "all", "allow": [] }], "no-shadow-restricted-names": 2, "no-undef": [2, { "typeof": true }], "no-undef-init": 2, "no-undefined": 0, "no-unused-vars": [2, { "vars": "local", "args": "none", "caughtErrors": "none" }], "no-use-before-define": [2, { "functions": false, "classes": true }], // Node.js and CommonJS (fully reviewed 2016-07-05) "callback-return": 0, "global-require": 0, "handle-callback-err": [2, "^(err|error)$" ], "no-mixed-requires": 0, "no-new-require": 2, "no-path-concat": 2, "no-process-env": 2, "no-process-exit": 2, "no-restricted-modules": 0, "no-sync": 2, // Stylistic Issues "block-spacing": 2, "brace-style": [2, "1tbs", { "allowSingleLine": true }], "camelcase": [2, { "properties": "never" }], "comma-dangle": [2, "never"], "comma-spacing": 2, "comma-style": 2, "eol-last": 2, "indent": [2, 4, { "SwitchCase": 1 }], "jsx-quotes": 0, "key-spacing": 2, "keyword-spacing": 2, "new-cap": 0, "new-parens": 2, "no-array-constructor": 2, "no-mixed-spaces-and-tabs": 2, "no-multiple-empty-lines": [2, { "max": 2, "maxBOF": 0, "maxEOF": 1 }], "no-new-object": 2, "no-plusplus": [2, { "allowForLoopAfterthoughts": false }], "no-spaced-func": 2, "no-trailing-spaces": 2, "no-unneeded-ternary": [2, { "defaultAssignment": false }], "no-whitespace-before-property": 2, "one-var": 0, "operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }], "padded-blocks": 0, "quotes": [2, "single", "avoid-escape"], "semi": [2, "always"], "semi-spacing": 2, "space-before-blocks": 2, "space-before-function-paren": [2, {"anonymous": "always", "named": "never"}], "space-in-parens": 0, "space-infix-ops": 0, "space-unary-ops": 2, "spaced-comment": 0 } } promise-core-1.1.3/.gitignore000066400000000000000000000000721355761740400161230ustar00rootroot00000000000000/.idea/ /coverage/ /node_modules/ .DS_Store npm-debug.logpromise-core-1.1.3/.npmignore000066400000000000000000000002041355761740400161270ustar00rootroot00000000000000/.idea/ /coverage/ /test/ /.editorconfig /.eslintrc.json /.gitignore /.publishrc /.travis.yml /gulpfile.js .DS_Store npm-debug.logpromise-core-1.1.3/.publishrc000066400000000000000000000004341355761740400161310ustar00rootroot00000000000000{ "validations": { "vulnerableDependencies": false, "uncommittedChanges": true, "untrackedFiles": true, "sensitiveData": true, "branch": "master", "gitTag": true }, "confirm": true, "publishTag": "latest", "prePublishScript": "npm run test-publish" }promise-core-1.1.3/.travis.yml000066400000000000000000000003471355761740400162510ustar00rootroot00000000000000language: node_js sudo: false node_js: - "0.10" - "0.12" - "iojs" - "4" - "6" - "8" - "10" env: - V_REQUEST=2.34.0 - V_REQUEST=latest before_script: - npm uninstall request - npm install request@$V_REQUEST promise-core-1.1.3/LICENSE000066400000000000000000000013741355761740400151460ustar00rootroot00000000000000ISC License Copyright (c) 2019, Nicolai Kamenzky and contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.promise-core-1.1.3/README.md000066400000000000000000000143241355761740400154170ustar00rootroot00000000000000 Promises/A+ logo # request-promise-core [![Gitter](https://img.shields.io/badge/gitter-join_chat-blue.svg?style=flat-square&maxAge=2592000)](https://gitter.im/request/request-promise?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status](https://img.shields.io/travis/request/promise-core/master.svg?style=flat-square&maxAge=2592000)](https://travis-ci.org/request/promise-core) [![Coverage Status](https://img.shields.io/coveralls/request/promise-core.svg?style=flat-square&maxAge=2592000)](https://coveralls.io/r/request/promise-core) [![Dependency Status](https://img.shields.io/david/request/promise-core.svg?style=flat-square&maxAge=2592000)](https://david-dm.org/request/promise-core) [![Known Vulnerabilities](https://snyk.io/test/npm/promise-core/badge.svg?style=flat-square&maxAge=2592000)](https://snyk.io/test/npm/promise-core) This package is the core for the following packages: - [`request-promise`](https://github.com/request/request-promise) - [`request-promise-any`](https://github.com/request/request-promise-any) - [`request-promise-bluebird`](https://github.com/request/request-promise-bluebird) - [`request-promise-native`](https://github.com/request/request-promise-native) `request-promise-core` contains the core logic to add Promise support to [`request`](https://github.com/request/request). Please use one of the libraries above. It is only recommended to use this library directly, if you have very specific requirements. ## Installation for `request@^2.34` This module is installed via npm: ``` npm install --save request npm install --save request-promise-core ``` `request` is defined as a peer-dependency and thus has to be installed separately. ## Usage for `request@^2.34` ``` js // 1. Load the request library // Only use a direct require if you are 100% sure that: // - Your project does not use request directly. That is without the Promise capabilities by calling require('request'). // - Any of the installed libraries use request. // ...because Request's prototype will be patched in step 2. /* var request = require('request'); */ // Instead use: var stealthyRequire = require('stealthy-require'); var request = stealthyRequire(require.cache, function () { return require('request'); }); // 2. Add Promise support to request var configure = require('request-promise-core/configure/request2'); configure({ request: request, // Pass your favorite ES6-compatible promise implementation PromiseImpl: Promise, // Expose all methods of the promise instance you want to call on the request(...) call expose: [ 'then', // Allows to use request(...).then(...) 'catch', // Allows to use request(...).catch(...) 'promise' // Allows to use request(...).promise() which returns the promise instance ], // Optional: Pass a callback that is called within the Promise constructor constructorMixin: function (resolve, reject) { // `this` is the request object // Additional arguments may be passed depending on the PromiseImpl used } }); // 3. Use request with its promise capabilities // E.g. crawl a web page: request('http://www.google.com') .then(function (htmlString) { // Process html... }) .catch(function (err) { // Crawling failed... }); ``` ## Installation and Usage for `request@next` [Request Next](https://github.com/request/request/issues/1982) is still in alpha. However, `request-promise-core` is already designed to be compatible and ships with a configuration helper – `require('request-promise-core/configure/request-next')` – that is [used by `request-promise`](https://github.com/request/request-promise/blob/next/lib/rp.js) in its "next" branch. ## Contributing To set up your development environment: 1. clone the repo to your desktop, 2. in the shell `cd` to the main folder, 3. hit `npm install`, 4. hit `npm install gulp -g` if you haven't installed gulp globally yet, and 5. run `gulp dev`. (Or run `node ./node_modules/.bin/gulp dev` if you don't want to install gulp globally.) `gulp dev` watches all source files and if you save some changes it will lint the code and execute all tests. The test coverage report can be viewed from `./coverage/lcov-report/index.html`. If you want to debug a test you should use `gulp test-without-coverage` to run all tests without obscuring the code by the test coverage instrumentation. ## Change History - 1.1.3 (2019-11-03) - Security fix: bumped `lodash` to `^4.17.15`. See [vulnerabilty reports](https://snyk.io/vuln/search?q=lodash&type=npm). *(Thanks to @daniel-nagy for pull request [#20](https://github.com/request/promise-core/pull/20) and thanks to @quetzaluz for reporting this in issue [#21](https://github.com/request/promise-core/issues/21).)* - 1.1.2 (2019-02-14) - Security fix: bumped `lodash` to `^4.17.11`. See [vulnerabilty reports](https://snyk.io/vuln/search?q=lodash&type=npm). *(Thanks to @lucaswillering and @sam-warren-finnair for reporting this in issues [#12](https://github.com/request/promise-core/issues/12) and [#13](https://github.com/request/promise-core/issues/13) and thanks to @Alec321 for pull request [#14](https://github.com/request/promise-core/pull/14).)* - 1.1.1 (2016-08-08) - Renamed package to `request-promise-core` because there were [too](https://github.com/request/request-promise/issues/137) [many](https://github.com/request/request-promise/issues/141) issues with the scoped package name `@request/promise-core` - 1.1.0 (2016-07-30) - Added `constructorMixin` option to enable [request/request-promise#123](https://github.com/request/request-promise/pull/123) - 1.0.0 (2016-07-15) - All tests green, ready for prime time - 1.0.0-rc.1 (2016-07-10) - Reimplementation of core logic based on `request-promise@3.0.0` - Plus `transform2xxOnly` option (fixes [request/request-promise#131](https://github.com/request/request-promise/issues/131)) ## License (ISC) In case you never heard about the [ISC license](http://en.wikipedia.org/wiki/ISC_license) it is functionally equivalent to the MIT license. See the [LICENSE file](LICENSE) for details. promise-core-1.1.3/configure/000077500000000000000000000000001355761740400161155ustar00rootroot00000000000000promise-core-1.1.3/configure/request-next.js000066400000000000000000000030401355761740400211140ustar00rootroot00000000000000'use strict'; var core = require('../'), isArray = require('lodash/isArray'), isFunction = require('lodash/isFunction'), isObjectLike = require('lodash/isObjectLike'); module.exports = function (options) { var errorText = 'Please verify options'; // For better minification because this string is repeating if (!isObjectLike(options)) { throw new TypeError(errorText); } if (!isFunction(options.client)) { throw new TypeError(errorText + '.client'); } if (!isArray(options.expose) || options.expose.length === 0) { throw new TypeError(errorText + '.expose'); } var thenExposed = false; for ( var i = 0; i < options.expose.length; i+=1 ) { if (options.expose[i] === 'then') { thenExposed = true; break; } } if (!thenExposed) { throw new Error('Please expose "then"'); } var plumbing = core({ PromiseImpl: options.PromiseImpl, constructorMixin: options.constructorMixin }); return function (requestOptions) { var self = {}; plumbing.init.call(self, requestOptions); var request = options.client(requestOptions); for ( var k = 0; k < options.expose.length; k+=1 ) { var method = options.expose[k]; plumbing[ method === 'promise' ? 'exposePromise' : 'exposePromiseMethod' ]( request, self, '_rp_promise', method ); } return request; }; }; promise-core-1.1.3/configure/request2.js000066400000000000000000000033751355761740400202350ustar00rootroot00000000000000'use strict'; var core = require('../'), isArray = require('lodash/isArray'), isFunction = require('lodash/isFunction'), isObjectLike = require('lodash/isObjectLike'); module.exports = function (options) { var errorText = 'Please verify options'; // For better minification because this string is repeating if (!isObjectLike(options)) { throw new TypeError(errorText); } if (!isFunction(options.request)) { throw new TypeError(errorText + '.request'); } if (!isArray(options.expose) || options.expose.length === 0) { throw new TypeError(errorText + '.expose'); } var plumbing = core({ PromiseImpl: options.PromiseImpl, constructorMixin: options.constructorMixin }); // Intercepting Request's init method var originalInit = options.request.Request.prototype.init; options.request.Request.prototype.init = function RP$initInterceptor(requestOptions) { // Init may be called again - currently in case of redirects if (isObjectLike(requestOptions) && !this._callback && !this._rp_promise) { plumbing.init.call(this, requestOptions); } return originalInit.apply(this, arguments); }; // Exposing the Promise capabilities var thenExposed = false; for ( var i = 0; i < options.expose.length; i+=1 ) { var method = options.expose[i]; plumbing[ method === 'promise' ? 'exposePromise' : 'exposePromiseMethod' ]( options.request.Request.prototype, null, '_rp_promise', method ); if (method === 'then') { thenExposed = true; } } if (!thenExposed) { throw new Error('Please expose "then"'); } }; promise-core-1.1.3/errors.js000066400000000000000000000000741355761740400160070ustar00rootroot00000000000000'use strict'; module.exports = require('./lib/errors.js'); promise-core-1.1.3/gulpfile.js000066400000000000000000000054471355761740400163130ustar00rootroot00000000000000'use strict'; var gulp = require('gulp'); var runSequence = require('run-sequence'); var istanbul = require('gulp-istanbul'); var mocha = require('gulp-mocha'); var chalk = require('chalk'); var rimraf = require('rimraf'); var coveralls = require('gulp-coveralls'); var eslint = require('gulp-eslint'); var _ = require('lodash'); var chai = require('chai'); global.expect = chai.expect; var paths = { libJsFiles: ['./configure/**/*.js', './lib/**/*.js', './errors.js'], specFiles: './test/spec/**/*.js', fixtureFiles: './test/fixtures/**/*.js', gulpfile: './gulpfile.js', eslintrc: './.eslintrc.json' }; gulp.task('dev', ['watch', 'validate']); gulp.task('watch', function () { gulp.watch(_.flatten([ paths.libJsFiles, paths.specFiles, paths.fixtureFiles, paths.gulpfile ]), [ 'validate' ]); gulp.watch(_.flatten([ paths.eslintrc ]), [ 'lint' ]); }); gulp.task('validate', function (done) { runSequence('lint', 'test', done); }); gulp.task('lint', function () { return gulp.src(_.flatten([ paths.libJsFiles, paths.gulpfile, paths.specFiles, paths.fixtureFiles, paths.gulpfile ])) .pipe(eslint()) .pipe(eslint.format()) .pipe(eslint.failAfterError()); }); gulp.task('test', ['clean'], function (done) { var coverageVariable = '$$cov_' + new Date().getTime() + '$$'; gulp.src(paths.libJsFiles) .pipe(istanbul({ coverageVariable: coverageVariable })) .pipe(istanbul.hookRequire()) .on('finish', function () { gulp.src(paths.specFiles) .pipe(mocha()) .on('error', function (err) { console.error(String(err)); console.error(chalk.bold.bgRed(' TESTS FAILED ')); done(new Error(' TESTS FAILED ')); }) .pipe(istanbul.writeReports({ reporters: ['lcov'], coverageVariable: coverageVariable })) .on('end', done); }); }); gulp.task('test-without-coverage', function () { return gulp.src(paths.specFiles) .pipe(mocha()) .on('error', function () { console.log(chalk.bold.bgRed(' TESTS FAILED ')); }); }); gulp.task('clean', ['clean-coverage']); gulp.task('clean-coverage', function (done) { rimraf('./coverage', done); }); gulp.task('ci', function (done) { runSequence('validate', 'coveralls', 'test-without-coverage', done); }); gulp.task('ci-no-cov', function (done) { runSequence('validate', 'test-without-coverage', done); }); gulp.task('coveralls', function () { return gulp.src('coverage/**/lcov.info') .pipe(coveralls()); }); promise-core-1.1.3/lib/000077500000000000000000000000001355761740400147025ustar00rootroot00000000000000promise-core-1.1.3/lib/errors.js000066400000000000000000000032051355761740400165540ustar00rootroot00000000000000'use strict'; function RequestError(cause, options, response) { this.name = 'RequestError'; this.message = String(cause); this.cause = cause; this.error = cause; // legacy attribute this.options = options; this.response = response; if (Error.captureStackTrace) { // required for non-V8 environments Error.captureStackTrace(this); } } RequestError.prototype = Object.create(Error.prototype); RequestError.prototype.constructor = RequestError; function StatusCodeError(statusCode, body, options, response) { this.name = 'StatusCodeError'; this.statusCode = statusCode; this.message = statusCode + ' - ' + (JSON && JSON.stringify ? JSON.stringify(body) : body); this.error = body; // legacy attribute this.options = options; this.response = response; if (Error.captureStackTrace) { // required for non-V8 environments Error.captureStackTrace(this); } } StatusCodeError.prototype = Object.create(Error.prototype); StatusCodeError.prototype.constructor = StatusCodeError; function TransformError(cause, options, response) { this.name = 'TransformError'; this.message = String(cause); this.cause = cause; this.error = cause; // legacy attribute this.options = options; this.response = response; if (Error.captureStackTrace) { // required for non-V8 environments Error.captureStackTrace(this); } } TransformError.prototype = Object.create(Error.prototype); TransformError.prototype.constructor = TransformError; module.exports = { RequestError: RequestError, StatusCodeError: StatusCodeError, TransformError: TransformError }; promise-core-1.1.3/lib/plumbing.js000066400000000000000000000132701355761740400170600ustar00rootroot00000000000000'use strict'; var errors = require('./errors.js'), isFunction = require('lodash/isFunction'), isObjectLike = require('lodash/isObjectLike'), isString = require('lodash/isString'), isUndefined = require('lodash/isUndefined'); module.exports = function (options) { var errorText = 'Please verify options'; // For better minification because this string is repeating if (!isObjectLike(options)) { throw new TypeError(errorText); } if (!isFunction(options.PromiseImpl)) { throw new TypeError(errorText + '.PromiseImpl'); } if (!isUndefined(options.constructorMixin) && !isFunction(options.constructorMixin)) { throw new TypeError(errorText + '.PromiseImpl'); } var PromiseImpl = options.PromiseImpl; var constructorMixin = options.constructorMixin; var plumbing = {}; plumbing.init = function (requestOptions) { var self = this; self._rp_promise = new PromiseImpl(function (resolve, reject) { self._rp_resolve = resolve; self._rp_reject = reject; if (constructorMixin) { constructorMixin.apply(self, arguments); // Using arguments since specific Promise libraries may pass additional parameters } }); self._rp_callbackOrig = requestOptions.callback; requestOptions.callback = self.callback = function RP$callback(err, response, body) { plumbing.callback.call(self, err, response, body); }; if (isString(requestOptions.method)) { requestOptions.method = requestOptions.method.toUpperCase(); } requestOptions.transform = requestOptions.transform || plumbing.defaultTransformations[requestOptions.method]; self._rp_options = requestOptions; self._rp_options.simple = requestOptions.simple !== false; self._rp_options.resolveWithFullResponse = requestOptions.resolveWithFullResponse === true; self._rp_options.transform2xxOnly = requestOptions.transform2xxOnly === true; }; plumbing.defaultTransformations = { HEAD: function (body, response, resolveWithFullResponse) { return resolveWithFullResponse ? response : response.headers; } }; plumbing.callback = function (err, response, body) { var self = this; var origCallbackThrewException = false, thrownException = null; if (isFunction(self._rp_callbackOrig)) { try { self._rp_callbackOrig.apply(self, arguments); // TODO: Apply to self mimics behavior of request@2. Is that also right for request@next? } catch (e) { origCallbackThrewException = true; thrownException = e; } } var is2xx = !err && /^2/.test('' + response.statusCode); if (err) { self._rp_reject(new errors.RequestError(err, self._rp_options, response)); } else if (self._rp_options.simple && !is2xx) { if (isFunction(self._rp_options.transform) && self._rp_options.transform2xxOnly === false) { (new PromiseImpl(function (resolve) { resolve(self._rp_options.transform(body, response, self._rp_options.resolveWithFullResponse)); // transform may return a Promise })) .then(function (transformedResponse) { self._rp_reject(new errors.StatusCodeError(response.statusCode, body, self._rp_options, transformedResponse)); }) .catch(function (transformErr) { self._rp_reject(new errors.TransformError(transformErr, self._rp_options, response)); }); } else { self._rp_reject(new errors.StatusCodeError(response.statusCode, body, self._rp_options, response)); } } else { if (isFunction(self._rp_options.transform) && (is2xx || self._rp_options.transform2xxOnly === false)) { (new PromiseImpl(function (resolve) { resolve(self._rp_options.transform(body, response, self._rp_options.resolveWithFullResponse)); // transform may return a Promise })) .then(function (transformedResponse) { self._rp_resolve(transformedResponse); }) .catch(function (transformErr) { self._rp_reject(new errors.TransformError(transformErr, self._rp_options, response)); }); } else if (self._rp_options.resolveWithFullResponse) { self._rp_resolve(response); } else { self._rp_resolve(body); } } if (origCallbackThrewException) { throw thrownException; } }; plumbing.exposePromiseMethod = function (exposeTo, bindTo, promisePropertyKey, methodToExpose, exposeAs) { exposeAs = exposeAs || methodToExpose; if (exposeAs in exposeTo) { throw new Error('Unable to expose method "' + exposeAs + '"'); } exposeTo[exposeAs] = function RP$exposed() { var self = bindTo || this; return self[promisePropertyKey][methodToExpose].apply(self[promisePropertyKey], arguments); }; }; plumbing.exposePromise = function (exposeTo, bindTo, promisePropertyKey, exposeAs) { exposeAs = exposeAs || 'promise'; if (exposeAs in exposeTo) { throw new Error('Unable to expose method "' + exposeAs + '"'); } exposeTo[exposeAs] = function RP$promise() { var self = bindTo || this; return self[promisePropertyKey]; }; }; return plumbing; }; promise-core-1.1.3/package.json000066400000000000000000000027431355761740400164300ustar00rootroot00000000000000{ "name": "request-promise-core", "version": "1.1.3", "description": "Core Promise support implementation for the simplified HTTP request client 'request'.", "keywords": [ "xhr", "http", "https", "promise", "request", "then", "thenable", "core" ], "main": "./lib/plumbing.js", "scripts": { "test": "./node_modules/.bin/gulp ci", "test-publish": "./node_modules/.bin/gulp ci-no-cov", "publish-please": "publish-please", "prepublish": "publish-please guard" }, "repository": { "type": "git", "url": "git+https://github.com/request/promise-core.git" }, "author": "Nicolai Kamenzky (https://github.com/analog-nico)", "license": "ISC", "bugs": { "url": "https://github.com/request/promise-core/issues" }, "homepage": "https://github.com/request/promise-core#readme", "engines": { "node": ">=0.10.0" }, "dependencies": { "lodash": "^4.17.15" }, "peerDependencies": { "request": "^2.34" }, "devDependencies": { "@request/api": "^0.6.0", "@request/client": "^0.1.0", "bluebird": "~3.4.1", "body-parser": "~1.15.2", "chai": "~3.5.0", "chalk": "~1.1.3", "gulp": "~3.9.1", "gulp-coveralls": "~0.1.4", "gulp-eslint": "~2.1.0", "gulp-istanbul": "~1.0.0", "gulp-mocha": "~2.2.0", "node-version": "~1.0.0", "publish-please": "~2.4.1", "request": "^2.34.0", "rimraf": "~2.5.3", "run-sequence": "~1.2.2", "stealthy-require": "~1.0.0" } } promise-core-1.1.3/test/000077500000000000000000000000001355761740400151135ustar00rootroot00000000000000promise-core-1.1.3/test/.eslintrc.json000066400000000000000000000002471355761740400177120ustar00rootroot00000000000000{ "env": { "mocha": true }, "globals": { "expect": true }, "rules": { // Node.js and CommonJS "no-process-env": 0, "no-sync": 0 } } promise-core-1.1.3/test/fixtures/000077500000000000000000000000001355761740400167645ustar00rootroot00000000000000promise-core-1.1.3/test/fixtures/server.js000066400000000000000000000022741355761740400206350ustar00rootroot00000000000000'use strict'; var bodyParser = require('body-parser'); var http = require('http'); var url = require('url'); module.exports = function startServer(port, cb) { var server = http.createServer(function (req, res) { bodyParser.json()(req, res, function () { var path = url.parse(req.url).pathname; var status = Number(path.split('?')[0].split('/')[1]); switch (status) { case 301: res.writeHead(301, { Location: '/200' }); res.end(); break; default: res.writeHead(status, {'Content-Type': 'text/plain'}); var body = req.method === 'POST' ? ' - ' + JSON.stringify(req.body) : ''; res.end(req.method + ' ' + path + body); } }); }); server.listen(port, function () { cb(function stopServer(done) { // Wait for all requests to finish since they may produce unhandled errors for tests at the end that don't wait themselves. setTimeout(function () { server.close(); done(); }, 20); }); }); }; promise-core-1.1.3/test/spec/000077500000000000000000000000001355761740400160455ustar00rootroot00000000000000promise-core-1.1.3/test/spec/plumbing.js000066400000000000000000001110461355761740400202230ustar00rootroot00000000000000'use strict'; var _ = require('lodash'), Bluebird = require('bluebird'), errors = require('../../errors'), plumbing = require('../../'); describe('Promise-Core\'s Plumbing', function () { it('should verify the options', function () { expect(function () { plumbing(); }).to.throw('Please verify options'); expect(function () { plumbing('not an object'); }).to.throw('Please verify options'); expect(function () { plumbing({}); }).to.throw('Please verify options.PromiseImpl'); expect(function () { plumbing({ PromiseImpl: 'not a function' }); }).to.throw('Please verify options.PromiseImpl'); expect(function () { plumbing({ PromiseImpl: function () {}, constructorMixin: false }); }).to.throw('Please verify options.PromiseImpl'); expect(function () { plumbing({ PromiseImpl: function () {}, constructorMixin: function () {} }); }).not.to.throw(); }); describe('should provide .init(...)', function () { var pl = null; before(function () { pl = plumbing({ PromiseImpl: Bluebird }); }); it('that sets up the promise and the resolve function', function (done) { var context = {}; pl.init.call(context, {}); expect(_.isFunction(context._rp_promise.then)).to.eql(true); expect(_.isFunction(context._rp_resolve)).to.eql(true); context._rp_resolve(); context._rp_promise .then(function () { done(); }) .catch(function (err) { done(err); }); }); it('that sets up the promise and the reject function', function (done) { var context = {}; pl.init.call(context, {}); expect(_.isFunction(context._rp_promise.then)).to.eql(true); expect(_.isFunction(context._rp_reject)).to.eql(true); context._rp_reject(new Error('Rejected by test case')); context._rp_promise .then(function () { done(new Error('Expected promise to be rejected.')); }) .catch(function (err) { expect(err.message).to.eql('Rejected by test case'); done(); }); }); it('that invokes the constructorMixin', function (done) { var pl2 = plumbing({ PromiseImpl: Bluebird, constructorMixin: function (resolve, reject) { if (this._rp_reject === reject) { reject('mixin invoked and this binding correct'); } else { reject('mixin invoked but this binding not correct'); } } }); var context = {}; pl2.init.call(context, {}); context._rp_promise .then(function () { done(new Error('Expected rejected promise')); }) .catch(function (message) { try { expect(message).to.eql('mixin invoked and this binding correct'); done(); } catch (e) { done(e); } }); }); it('that sets up the default options', function () { var context = {}; pl.init.call(context, {}); expect(_.isFunction(context._rp_options.callback)).to.eql(true); delete context._rp_options.callback; expect(context._rp_options).to.eql({ simple: true, resolveWithFullResponse: false, transform: undefined, transform2xxOnly: false }); }); it('that forwards any custom options', function () { var context = {}; pl.init.call(context, { custom: 'test' }); delete context._rp_options.callback; expect(context._rp_options).to.eql({ custom: 'test', simple: true, resolveWithFullResponse: false, transform: undefined, transform2xxOnly: false }); }); it('that allows custom values for the Request-Promise options', function () { var customTransform = function () {}; var context = {}; pl.init.call(context, { simple: false, resolveWithFullResponse: true, transform: customTransform, transform2xxOnly: true }); delete context._rp_options.callback; expect(context._rp_options).to.eql({ simple: false, resolveWithFullResponse: true, transform: customTransform, transform2xxOnly: true }); }); it('that converts the method to upper case', function () { var context = {}; pl.init.call(context, { method: 'get' }); expect(context._rp_options.method).to.eql('GET'); }); it('that applies a default transform for HEAD requests', function () { var context = {}; pl.init.call(context, { method: 'head' }); expect(context._rp_options.transform).to.eql(pl.defaultTransformations.HEAD); }); it('that keeps the already existing callback', function () { var alreadyExistingCallback = function () {}; var context = {}; pl.init.call(context, { callback: alreadyExistingCallback }); expect(context._rp_callbackOrig).to.eql(alreadyExistingCallback); }); }); describe('should provide .callback(...)', function () { var pl = null; before(function () { pl = plumbing({ PromiseImpl: Bluebird }); }); it('that rejects if an error is passed', function (done) { var context = {}; pl.init.call(context, {}); var passedError = new Error('test error'); pl.callback.call(context, passedError, 'dummy response'); context._rp_promise .then(function () { done(new Error('Expected promise to be rejected.')); }) .catch(function (err) { expect(err instanceof errors.RequestError).to.eql(true); expect(err.name).to.eql('RequestError'); expect(err.message).to.eql(String(passedError)); expect(err.cause).to.eql(passedError); expect(err.error).to.eql(passedError); expect(err.options).to.eql(context._rp_options); expect(err.response).to.eql('dummy response'); done(); }); }); it('that resolves a 200 response', function (done) { var context = {}; pl.init.call(context, {}); var response = { statusCode: 200, body: { a: 'b' } }; pl.callback.call(context, null, response, response.body); context._rp_promise .then(function (body) { expect(body).to.eql(response.body); done(); }) .catch(function (err) { done(err); }); }); it('that resolves a 201 response', function (done) { var context = {}; pl.init.call(context, {}); var response = { statusCode: 201, body: { a: 'b' } }; pl.callback.call(context, null, response, response.body); context._rp_promise .then(function (body) { expect(body).to.eql(response.body); done(); }) .catch(function (err) { done(err); }); }); it('that resolves a 2xx response with full response', function (done) { var context = {}; pl.init.call(context, { resolveWithFullResponse: true }); var response = { statusCode: 201, body: { a: 'b' } }; pl.callback.call(context, null, response, response.body); context._rp_promise .then(function (fullResponse) { expect(fullResponse).to.eql(response); done(); }) .catch(function (err) { done(err); }); }); it('that rejects a non-2xx response in simple mode', function (done) { var context = {}; pl.init.call(context, {}); var response = { statusCode: 404, body: { a: 'b' } }; pl.callback.call(context, null, response, response.body); context._rp_promise .then(function () { done(new Error('Expected promise to be rejected.')); }) .catch(function (err) { expect(err instanceof errors.StatusCodeError).to.eql(true); expect(err.name).to.eql('StatusCodeError'); expect(err.statusCode).to.eql(404); expect(err.message).to.eql('404 - {"a":"b"}'); expect(err.error).to.eql(response.body); expect(err.options).to.eql(context._rp_options); expect(err.response).to.eql(response); done(); }); }); it('that resolves a non-2xx response in non-simple mode', function (done) { var context = {}; pl.init.call(context, { simple: false }); var response = { statusCode: 404, body: { a: 'b' } }; pl.callback.call(context, null, response, response.body); context._rp_promise .then(function (body) { expect(body).to.eql(response.body); done(); }) .catch(function (err) { done(err); }); }); it('that applies the transform function to 2xx responses', function (done) { var context = {}; pl.init.call(context, { transform: function (body, response, resolveWithFullResponse) { return JSON.stringify(body) + ' - ' + JSON.stringify(response) + ' - ' + resolveWithFullResponse; } }); var res = { statusCode: 200, body: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function (transformed) { expect(transformed).to.eql(JSON.stringify(res.body) + ' - ' + JSON.stringify(res) + ' - false'); done(); }) .catch(function (err) { done(err); }); }); it('that applies the transform function to 2xx responses which throws an error', function (done) { var cause = new Error('transform failed'); var context = {}; pl.init.call(context, { transform: function (body, response, resolveWithFullResponse) { throw cause; } }); var res = { statusCode: 200, body: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function () { done(new Error('Expected promise to be rejected.')); }) .catch(function (err) { expect(err instanceof errors.TransformError).to.eql(true); expect(err.name).to.eql('TransformError'); expect(err.message).to.eql(String(cause)); expect(err.cause).to.eql(cause); expect(err.error).to.eql(cause); expect(err.options).to.eql(context._rp_options); expect(err.response).to.eql(res); done(); }); }); it('that applies the transform function to 2xx responses which returns a promise', function (done) { var context = {}; pl.init.call(context, { transform: function (body, response, resolveWithFullResponse) { return Bluebird.resolve(JSON.stringify(body) + ' - ' + JSON.stringify(response) + ' - ' + resolveWithFullResponse); } }); var res = { statusCode: 200, body: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function (transformed) { expect(transformed).to.eql(JSON.stringify(res.body) + ' - ' + JSON.stringify(res) + ' - false'); done(); }) .catch(function (err) { done(err); }); }); it('that applies the transform function to 2xx responses which returns a rejected promise', function (done) { var cause = new Error('transform failed'); var context = {}; pl.init.call(context, { transform: function (body, response, resolveWithFullResponse) { return Bluebird.reject(cause); } }); var res = { statusCode: 200, body: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function () { done(new Error('Expected promise to be rejected.')); }) .catch(function (err) { expect(err instanceof errors.TransformError).to.eql(true); expect(err.name).to.eql('TransformError'); expect(err.message).to.eql(String(cause)); expect(err.cause).to.eql(cause); expect(err.error).to.eql(cause); expect(err.options).to.eql(context._rp_options); expect(err.response).to.eql(res); done(); }); }); it('that applies the transform function to 2xx responses for simple = true and transform2xxOnly = true', function (done) { var context = {}; pl.init.call(context, { transform: function (body, response, resolveWithFullResponse) { return JSON.stringify(body) + ' - ' + JSON.stringify(response) + ' - ' + resolveWithFullResponse; }, transform2xxOnly: true }); var res = { statusCode: 200, body: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function (transformed) { expect(transformed).to.eql(JSON.stringify(res.body) + ' - ' + JSON.stringify(res) + ' - false'); done(); }) .catch(function (err) { done(err); }); }); it('that applies the transform function to 2xx responses for simple = false and transform2xxOnly = true', function (done) { var context = {}; pl.init.call(context, { simple: false, transform: function (body, response, resolveWithFullResponse) { return JSON.stringify(body) + ' - ' + JSON.stringify(response) + ' - ' + resolveWithFullResponse; }, transform2xxOnly: true }); var res = { statusCode: 200, body: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function (transformed) { expect(transformed).to.eql(JSON.stringify(res.body) + ' - ' + JSON.stringify(res) + ' - false'); done(); }) .catch(function (err) { done(err); }); }); it('that applies the transform function to non-2xx responses in simple mode', function (done) { var context = {}; pl.init.call(context, { transform: function (body, response, resolveWithFullResponse) { return JSON.stringify(body) + ' - ' + JSON.stringify(response) + ' - ' + resolveWithFullResponse; } }); var res = { statusCode: 404, body: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function () { done(new Error('Expected promise to be rejected.')); }) .catch(function (err) { expect(err instanceof errors.StatusCodeError).to.eql(true); expect(err.name).to.eql('StatusCodeError'); expect(err.statusCode).to.eql(404); expect(err.message).to.eql('404 - {"a":"b"}'); expect(err.error).to.eql(res.body); expect(err.options).to.eql(context._rp_options); expect(err.response).to.eql(JSON.stringify(res.body) + ' - ' + JSON.stringify(res) + ' - false'); done(); }); }); it('that applies the transform function to non-2xx responses in simple mode which throws an error', function (done) { var cause = new Error('transform failed'); var context = {}; pl.init.call(context, { transform: function (body, response, resolveWithFullResponse) { throw cause; } }); var res = { statusCode: 404, body: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function () { done(new Error('Expected promise to be rejected.')); }) .catch(function (err) { expect(err instanceof errors.TransformError).to.eql(true); expect(err.name).to.eql('TransformError'); expect(err.message).to.eql(String(cause)); expect(err.cause).to.eql(cause); expect(err.error).to.eql(cause); expect(err.options).to.eql(context._rp_options); expect(err.response).to.eql(res); done(); }); }); it('that applies the transform function to non-2xx responses in simple mode which returns a promise', function (done) { var context = {}; pl.init.call(context, { transform: function (body, response, resolveWithFullResponse) { return Bluebird.resolve(JSON.stringify(body) + ' - ' + JSON.stringify(response) + ' - ' + resolveWithFullResponse); } }); var res = { statusCode: 404, body: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function () { done(new Error('Expected promise to be rejected.')); }) .catch(function (err) { expect(err instanceof errors.StatusCodeError).to.eql(true); expect(err.name).to.eql('StatusCodeError'); expect(err.statusCode).to.eql(404); expect(err.message).to.eql('404 - {"a":"b"}'); expect(err.error).to.eql(res.body); expect(err.options).to.eql(context._rp_options); expect(err.response).to.eql(JSON.stringify(res.body) + ' - ' + JSON.stringify(res) + ' - false'); done(); }); }); it('that applies the transform function to non-2xx responses in simple mode which returns a rejected promise', function (done) { var cause = new Error('transform failed'); var context = {}; pl.init.call(context, { transform: function (body, response, resolveWithFullResponse) { return Bluebird.reject(cause); } }); var res = { statusCode: 404, body: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function () { done(new Error('Expected promise to be rejected.')); }) .catch(function (err) { expect(err instanceof errors.TransformError).to.eql(true); expect(err.name).to.eql('TransformError'); expect(err.message).to.eql(String(cause)); expect(err.cause).to.eql(cause); expect(err.error).to.eql(cause); expect(err.options).to.eql(context._rp_options); expect(err.response).to.eql(res); done(); }); }); it('that applies the transform function to non-2xx responses for simple = false and transform2xxOnly = false', function (done) { var context = {}; pl.init.call(context, { simple: false, transform: function (body, response, resolveWithFullResponse) { return JSON.stringify(body) + ' - ' + JSON.stringify(response) + ' - ' + resolveWithFullResponse; } }); var res = { statusCode: 404, body: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function (transformed) { expect(transformed).to.eql(JSON.stringify(res.body) + ' - ' + JSON.stringify(res) + ' - false'); done(); }) .catch(function (err) { done(err); }); }); it('that does not apply the transform function to non-2xx responses for simple = true and transform2xxOnly = false', function (done) { var context = {}; pl.init.call(context, { transform: function (body, response, resolveWithFullResponse) { return JSON.stringify(body) + ' - ' + JSON.stringify(response) + ' - ' + resolveWithFullResponse; }, transform2xxOnly: true }); var res = { statusCode: 404, body: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function () { done(new Error('Expected promise to be rejected.')); }) .catch(function (err) { expect(err instanceof errors.StatusCodeError).to.eql(true); expect(err.name).to.eql('StatusCodeError'); expect(err.statusCode).to.eql(404); expect(err.message).to.eql('404 - {"a":"b"}'); expect(err.error).to.eql(res.body); expect(err.options).to.eql(context._rp_options); expect(err.response).to.eql(res); done(); }); }); it('that does not apply the transform function to non-2xx responses for simple = false and transform2xxOnly = false', function (done) { var context = {}; pl.init.call(context, { simple: false, transform: function (body, response, resolveWithFullResponse) { return JSON.stringify(body) + ' - ' + JSON.stringify(response) + ' - ' + resolveWithFullResponse; }, transform2xxOnly: true }); var res = { statusCode: 404, body: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function (body) { expect(body).to.eql(res.body); done(); }) .catch(function (err) { done(err); }); }); it('that applies the default HEAD transform', function (done) { var context = {}; pl.init.call(context, { method: 'HEAD' }); var res = { statusCode: 200, headers: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function (transformed) { expect(transformed).to.eql(res.headers); done(); }) .catch(function (err) { done(err); }); }); it('that applies the default HEAD transform doing nothing when resolving full response', function (done) { var context = {}; pl.init.call(context, { method: 'HEAD', resolveWithFullResponse: true }); var res = { statusCode: 200, headers: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function (transformed) { expect(transformed).to.eql(res); done(); }) .catch(function (err) { done(err); }); }); it('that applies a custom HEAD transform', function (done) { var context = {}; pl.init.call(context, { method: 'HEAD', transform: function () { return 'custom'; } }); var res = { statusCode: 200, headers: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function (transformed) { expect(transformed).to.eql('custom'); done(); }) .catch(function (err) { done(err); }); }); it('that ignores the transform option if it is not a function', function (done) { // IMHO input validation should reject this but behavior is kept this way for backwards compatibility. var context = {}; pl.init.call(context, { method: 'HEAD', transform: 'not a function', resolveWithFullResponse: true }); var res = { statusCode: 200, headers: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function (response) { expect(response.headers).to.eql(res.headers); done(); }) .catch(function (err) { done(err); }); }); it('that ignores the transform option for non-2xx responses if it is not a function', function (done) { // IMHO input validation should reject this but behavior is kept this way for backwards compatibility. var context = {}; pl.init.call(context, { method: 'HEAD', transform: 'not a function', resolveWithFullResponse: true }); var res = { statusCode: 404, headers: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function () { done(new Error('Expected promise to be rejected.')); }) .catch(function (err) { expect(err instanceof errors.StatusCodeError).to.eql(true); expect(err.name).to.eql('StatusCodeError'); expect(err.statusCode).to.eql(404); expect(err.message).to.eql('404 - undefined'); expect(err.error).to.eql(res.body); expect(err.options).to.eql(context._rp_options); expect(err.response).to.eql(res); done(); }); }); it('that also calls an already existing callback', function (done) { var callbackWasCalled = 0; var callbackArgs = {}; var context = {}; pl.init.call(context, { callback: function (err, response, body) { callbackWasCalled += 1; callbackArgs.err = err; callbackArgs.response = response; callbackArgs.body = body; } }); var res = { statusCode: 200, body: { a: 'b' } }; pl.callback.call(context, null, res, res.body); context._rp_promise .then(function (body) { expect(body).to.eql(res.body); expect(callbackWasCalled).to.eql(1); expect(callbackArgs).to.eql({ err: null, response: res, body: res.body }); done(); }) .catch(function (err) { done(err); }); }); it('that also calls an already existing callback while handlings an error it throws', function (done) { var error = new Error('thrown by callback'); var context = {}; pl.init.call(context, { callback: function () { throw error; } }); var res = { statusCode: 200, body: { a: 'b' } }; expect(function () { pl.callback.call(context, null, res, res.body); }).to.throw('thrown by callback'); context._rp_promise .then(function (body) { expect(body).to.eql(res.body); done(); }) .catch(function (err) { done(err); }); }); }); describe('should expose a method', function () { var exposePromiseMethod = plumbing({ PromiseImpl: Bluebird }).exposePromiseMethod; it('with default binding', function () { var target = { fakePromise: { attr: 5, then: function () { return this.attr; } } }; exposePromiseMethod(target, null, 'fakePromise', 'then'); expect(target.then()).to.eql(5); }); it('with custom binding', function () { var target = {}; var source = { fakePromise: { attr: 5, then: function () { return this.attr; } } }; exposePromiseMethod(target, source, 'fakePromise', 'then'); expect(target.then()).to.eql(5); }); it('with a different name', function () { var target = { fakePromise: { attr: 5, then: function () { return this.attr; } } }; exposePromiseMethod(target, null, 'fakePromise', 'then', 'next'); expect(target.next()).to.eql(5); }); it('and not overwrite existing method', function () { var target = { fakePromise: { attr: 5, then: function () { return this.attr; } } }; expect(function () { exposePromiseMethod(target, null, 'fakePromise', 'then', 'fakePromise'); }).to.throw('Unable to expose method "fakePromise"'); }); it('and forward arguments when called', function () { var target = { fakePromise: { attr: 5, then: function (a, b) { return this.attr + a + b; } } }; exposePromiseMethod(target, null, 'fakePromise', 'then'); expect(target.then(7, 11)).to.eql(5+7+11); }); }); describe('should expose the promise', function () { var exposePromise = plumbing({ PromiseImpl: Bluebird }).exposePromise; it('with default binding', function () { var target = { fakePromise: { attr: 5, then: function () { return this.attr; } } }; exposePromise(target, null, 'fakePromise'); expect(target.promise().then()).to.eql(5); }); it('with custom binding', function () { var target = {}; var source = { fakePromise: { attr: 5, then: function () { return this.attr; } } }; exposePromise(target, source, 'fakePromise'); expect(target.promise().then()).to.eql(5); }); it('with a different name', function () { var target = { fakePromise: { attr: 5, then: function () { return this.attr; } } }; exposePromise(target, null, 'fakePromise', 'promise2'); expect(target.promise2().then()).to.eql(5); }); it('and not overwrite existing method', function () { var target = { fakePromise: { attr: 5, then: function () { return this.attr; } } }; expect(function () { exposePromise(target, null, 'fakePromise', 'fakePromise'); }).to.throw('Unable to expose method "fakePromise"'); }); }); }); promise-core-1.1.3/test/spec/request-next.js000066400000000000000000000220321355761740400210460ustar00rootroot00000000000000'use strict'; var Bluebird = require('bluebird'), configure = require('../../configure/request-next.js'), errors = require('../../errors'), nodeVersion = require('node-version'), startServer = require('../fixtures/server.js'); describe('Promise-Core for Request@next', function () { if (Number(nodeVersion.major) < 4) { return; // request@next uses ES6 and thus wouldn't run on old node.js versions } var api = require('@request/api'), client = require('@request/client'); describe('during configuration', function () { it('should verify the options', function () { expect(function () { configure(); }).to.throw('Please verify options'); expect(function () { configure('not an object'); }).to.throw('Please verify options'); expect(function () { configure({}); }).to.throw('Please verify options.client'); expect(function () { configure({ client: 'not a function' }); }).to.throw('Please verify options.client'); expect(function () { configure({ client: client }); }).to.throw('Please verify options.expose'); expect(function () { configure({ client: client, expose: 'not an array' }); }).to.throw('Please verify options.expose'); expect(function () { configure({ client: client, expose: [] }); }).to.throw('Please verify options.expose'); expect(function () { configure({ client: client, expose: ['then', 'promise'] }); }).to.throw('Please verify options.PromiseImpl'); expect(function () { configure({ client: client, expose: ['then', 'promise'], PromiseImpl: 'not a function' }); }).to.throw('Please verify options.PromiseImpl'); expect(function () { configure({ client: client, expose: ['then', 'promise'], PromiseImpl: Bluebird }); }).not.to.throw(); expect(function () { configure({ client: client, expose: ['promise'], PromiseImpl: Bluebird }); }).to.throw('Please expose "then"'); }); it('should forward the constructorMixin', function () { var mixinCalled = false; // eslint-disable-line no-unused-vars var request = api({ type: 'basic', define: { request: configure({ client: client, PromiseImpl: Bluebird, expose: [ 'then', 'catch' ], constructorMixin: function () { mixinCalled = true; } }) } }); return request('http://localhost:4000') // not started yet so expecting ECONNREFUSED .catch(function () { expect(mixinCalled).to.eql(true); }); }); }); /** * The following tests are testing the correct integration of plumbing.init and plumbing.callback. * * That means their test coverage is not 100% (the plumbing unit tests already do that) * but instead focus on the following integration aspects: * - All input parameters are passed to the two functions as expected. * - All return values of the two functions are processed by Request as expected. * - All operations on the context (this) of the two functions have the expected effect. * - Plus 100% coverage of the configuration code. */ describe('doing requests', function () { var request = null, stopServer = null; before(function (done) { request = api({ type: 'basic', define: { request: configure({ client: client, PromiseImpl: Bluebird, expose: [ 'then', 'catch', 'finally', 'promise' ] }) } }); startServer(4000, function (stop) { stopServer = stop; done(); }); }); after(function (done) { stopServer(done); }); it('that is successful', function (done) { request('http://localhost:4000/200') .then(function (body) { expect(body).to.eql('GET /200'); done(); }) .catch(function (err) { done(err); }); }); // TODO: Check if request@next fixed passing the response to the callback xit('that is successful with non-default options', function (done) { request({ uri: 'http://localhost:4000/404', simple: false, resolveWithFullResponse: true, transform: function () { return 'must not be called'; }, transform2xxOnly: true }) .then(function (response) { expect(response.body).to.eql('GET /404'); done(); }) .catch(function (err) { done(err); }); }); it('with method "post" in lower case', function (done) { request({ method: 'post', uri: 'http://localhost:4000/200', body: { a: 'b' }, json: true }) .then(function (body) { // TODO: Check if request@next fixed sending the body // expect(body).to.eql('POST /200 - {"a":"b"}'); expect(body).to.eql('POST /200 - {}'); done(); }) .catch(function (err) { done(err); }); }); it('with a transform function', function (done) { request({ method: 'post', uri: 'http://localhost:4000/200', body: { a: 'b' }, json: true, transform: function (body, response, resolveWithFullResponse) { return body.split('').reverse().join(''); } }) .then(function (body) { // TODO: Check if request@next fixed sending the body // expect(body).to.eql('POST /200 - {"a":"b"}'.split('').reverse().join('')); expect(body).to.eql('POST /200 - {}'.split('').reverse().join('')); done(); }) .catch(function (err) { done(err); }); }); it('that fails', function (done) { request('http://localhost:1/200') .then(function () { done(new Error('Expected promise to be rejected.')); }) .catch(function (err) { expect(err instanceof errors.RequestError).to.eql(true); done(); }); }); it('that gets a 500 response', function (done) { request('http://localhost:4000/500') .then(function () { done(new Error('Expected promise to be rejected.')); }) .catch(function (err) { expect(err instanceof errors.StatusCodeError).to.eql(true); done(); }); }); it('calling the callback, too', function (done) { var callbackWasCalled = false; request('http://localhost:4000/200', function () { callbackWasCalled = true; }) .then(function (body) { expect(body).to.eql('GET /200'); expect(callbackWasCalled).to.eql(true); done(); }) .catch(function (err) { done(err); }); }); }); describe('should support Request\'s', function () { // TODO: Add tests for Request's non-promise related features }); }); promise-core-1.1.3/test/spec/request2.js000066400000000000000000000300231355761740400201530ustar00rootroot00000000000000'use strict'; var Bluebird = require('bluebird'), configure = require('../../configure/request2.js'), errors = require('../../errors'), stealthyRequire = require('stealthy-require'), startServer = require('../fixtures/server.js'); describe('Promise-Core for Request@2', function () { describe('during configuration', function () { it('should verify the options', function () { var request = stealthyRequire(require.cache, function () { return require('request'); }); expect(function () { configure(); }).to.throw('Please verify options'); expect(function () { configure('not an object'); }).to.throw('Please verify options'); expect(function () { configure({}); }).to.throw('Please verify options.request'); expect(function () { configure({ request: 'not a function' }); }).to.throw('Please verify options.request'); expect(function () { configure({ request: request }); }).to.throw('Please verify options.expose'); expect(function () { configure({ request: request, expose: 'not an array' }); }).to.throw('Please verify options.expose'); expect(function () { configure({ request: request, expose: [] }); }).to.throw('Please verify options.expose'); expect(function () { configure({ request: request, expose: ['then', 'promise'] }); }).to.throw('Please verify options.PromiseImpl'); expect(function () { configure({ request: request, expose: ['then', 'promise'], PromiseImpl: 'not a function' }); }).to.throw('Please verify options.PromiseImpl'); expect(function () { configure({ request: request, expose: ['then', 'promise'], PromiseImpl: Bluebird }); }).not.to.throw(); request = stealthyRequire(require.cache, function () { return require('request'); }); expect(function () { configure({ request: request, expose: ['promise'], PromiseImpl: Bluebird }); }).to.throw('Please expose "then"'); }); it('should forward the constructorMixin', function () { var mixinCalled = false; // eslint-disable-line no-unused-vars var request = stealthyRequire(require.cache, function () { return require('request'); }); configure({ request: request, expose: ['then', 'catch'], PromiseImpl: Bluebird, constructorMixin: function () { mixinCalled = true; } }); return request('http://localhost:4000') // not started yet so expecting ECONNREFUSED .catch(function () { expect(mixinCalled).to.eql(true); }); }); }); /** * The following tests are testing the correct integration of plumbing.init and plumbing.callback. * * That means their test coverage is not 100% (the plumbing unit tests already do that) * but instead focus on the following integration aspects: * - All input parameters are passed to the two functions as expected. * - All return values of the two functions are processed by Request as expected. * - All operations on the context (this) of the two functions have the expected effect. * - Plus 100% coverage of the configuration code. */ describe('doing requests', function () { var request = null, stopServer = null; before(function (done) { request = stealthyRequire(require.cache, function () { return require('request'); }); configure({ request: request, PromiseImpl: Bluebird, expose: [ 'then', 'catch', 'finally', 'promise' ] }); startServer(4000, function (stop) { stopServer = stop; done(); }); }); after(function (done) { stopServer(done); }); it('that is successful', function (done) { request('http://localhost:4000/200') .then(function (body) { expect(body).to.eql('GET /200'); done(); }) .catch(function (err) { done(err); }); }); it('that is successful with non-default options', function (done) { request({ uri: 'http://localhost:4000/404', simple: false, resolveWithFullResponse: true, transform: function () { return 'must not be called'; }, transform2xxOnly: true }) .then(function (response) { expect(response.body).to.eql('GET /404'); done(); }) .catch(function (err) { done(err); }); }); it('with method "post" in lower case', function (done) { request({ method: 'post', uri: 'http://localhost:4000/200', body: { a: 'b' }, json: true }) .then(function (body) { expect(body).to.eql('POST /200 - {"a":"b"}'); done(); }) .catch(function (err) { done(err); }); }); it('with a transform function', function (done) { request({ method: 'post', uri: 'http://localhost:4000/200', body: { a: 'b' }, json: true, transform: function (body, response, resolveWithFullResponse) { return body.split('').reverse().join(''); } }) .then(function (body) { expect(body).to.eql('POST /200 - {"a":"b"}'.split('').reverse().join('')); done(); }) .catch(function (err) { done(err); }); }); it('that is successfully redirected', function (done) { request('http://localhost:4000/301') .then(function (body) { expect(body).to.eql('GET /200'); done(); }) .catch(function (err) { done(err); }); }); it('that fails', function (done) { request('http://localhost:1/200') .then(function () { done(new Error('Expected promise to be rejected.')); }) .catch(function (err) { expect(err instanceof errors.RequestError).to.eql(true); done(); }); }); it('that gets a 500 response', function (done) { request('http://localhost:4000/500') .then(function () { done(new Error('Expected promise to be rejected.')); }) .catch(function (err) { expect(err instanceof errors.StatusCodeError).to.eql(true); done(); }); }); it('calling the callback, too', function (done) { var callbackWasCalled = false; request('http://localhost:4000/200', function () { callbackWasCalled = true; }) .then(function (body) { expect(body).to.eql('GET /200'); expect(callbackWasCalled).to.eql(true); done(); }) .catch(function (err) { done(err); }); }); }); describe('should support Request\'s', function () { var request = null, stopServer = null; before(function (done) { request = stealthyRequire(require.cache, function () { return require('request'); }); configure({ request: request, PromiseImpl: Bluebird, expose: [ 'then', 'catch', 'finally', 'promise' ] }); startServer(4000, function (stop) { stopServer = stop; done(); }); }); after(function (done) { stopServer(done); }); it('method shortcuts', function (done) { request.post({ uri: 'http://localhost:4000/404', body: { a: 'b' }, json: true, simple: false // <-- ensures that parameter is forwarded }) .then(function (body) { expect(body).to.eql('POST /404 - {"a":"b"}'); done(); }) .catch(function (err) { done(err); }); }); it('.defaults(...) feature', function (done) { var rpSimpleOff = request.defaults({ simple: false }); rpSimpleOff({ uri: 'http://localhost:4000/404', resolveWithFullResponse: true }) .then(function (response) { expect(response.body).to.eql('GET /404'); done(); }) .catch(function (err) { done(err); }); }); if (process.env.V_REQUEST !== '2.34.0') { // Was never supported in this version so fixing it wouldn't make sense. it('.defaults(...) feature using it multiple times', function (done) { var rpSimpleOff = request.defaults({ simple: false }); var rpSimpleOffWithFullResp = rpSimpleOff.defaults({ resolveWithFullResponse: true }); rpSimpleOffWithFullResp('http://localhost:4000/404') .then(function (response) { expect(response.body).to.eql('GET /404'); done(); }) .catch(function (err) { done(err); }); }); } it('event emitter', function (done) { request('http://localhost:4000/200') .on('complete', function (httpResponse, body) { expect(httpResponse.statusCode).to.eql(200); expect(body).to.eql('GET /200'); done(); }); }); it('main function to take extra options as the second parameter', function (done) { request('http://localhost:4000/200', { method: 'POST', json: { foo: 'bar' } }) .then(function (body) { expect(body).to.eql('POST /200 - {"foo":"bar"}'); done(); }) .catch(function (err) { done(err); }); }); }); });