[
  {
    "path": ".codeclimate.yml",
    "content": "---\nengines:\n  duplication:\n    enabled: true\n    config:\n      languages:\n      - ruby\n      - javascript\n      - python\n      - php\n  eslint:\n    enabled: true\n  fixme:\n    enabled: true\nratings:\n  paths:\n  - \"**.inc\"\n  - \"**.js\"\n  - \"**.jsx\"\n  - \"**.module\"\n  - \"**.php\"\n  - \"**.py\"\n  - \"**.rb\"\nexclude_paths:\n- test/\n"
  },
  {
    "path": ".eslintignore",
    "content": "**/*{.,-}min.js\n"
  },
  {
    "path": ".eslintrc",
    "content": "env:\n  amd: true\n  browser: true\n  es6: true\n  jquery: true\n  node: true\n\n# http://eslint.org/docs/rules/\nrules:\n  # Possible Errors\n  comma-dangle: [2, never]\n  no-cond-assign: 2\n  no-console: 0\n  no-constant-condition: 2\n  no-control-regex: 2\n  no-debugger: 2\n  no-dupe-args: 2\n  no-dupe-keys: 2\n  no-duplicate-case: 2\n  no-empty: 2\n  no-empty-character-class: 2\n  no-ex-assign: 2\n  no-extra-boolean-cast: 2\n  no-extra-parens: 0\n  no-extra-semi: 2\n  no-func-assign: 2\n  no-inner-declarations: [2, functions]\n  no-invalid-regexp: 2\n  no-irregular-whitespace: 2\n  no-negated-in-lhs: 2\n  no-obj-calls: 2\n  no-regex-spaces: 2\n  no-sparse-arrays: 2\n  no-unexpected-multiline: 2\n  no-unreachable: 2\n  use-isnan: 2\n  valid-jsdoc: 0\n  valid-typeof: 2\n\n  # Best Practices\n  accessor-pairs: 2\n  block-scoped-var: 0\n  complexity: [2, 7]\n  consistent-return: 0\n  curly: 0\n  default-case: 0\n  dot-location: 0\n  dot-notation: 0\n  eqeqeq: 2\n  guard-for-in: 2\n  no-alert: 2\n  no-caller: 2\n  no-case-declarations: 2\n  no-div-regex: 2\n  no-else-return: 0\n  no-empty-pattern: 2\n  no-eq-null: 2\n  no-eval: 2\n  no-extend-native: 2\n  no-extra-bind: 2\n  no-fallthrough: 2\n  no-floating-decimal: 0\n  no-implicit-coercion: 0\n  no-implied-eval: 2\n  no-invalid-this: 0\n  no-iterator: 2\n  no-labels: 0\n  no-lone-blocks: 2\n  no-loop-func: 2\n  no-magic-number: 0\n  no-multi-spaces: 0\n  no-multi-str: 0\n  no-native-reassign: 2\n  no-new-func: 2\n  no-new-wrappers: 2\n  no-new: 2\n  no-octal-escape: 2\n  no-octal: 2\n  no-proto: 2\n  no-redeclare: 2\n  no-return-assign: 2\n  no-script-url: 2\n  no-self-compare: 2\n  no-sequences: 0\n  no-throw-literal: 0\n  no-unused-expressions: 2\n  no-useless-call: 2\n  no-useless-concat: 2\n  no-void: 2\n  no-warning-comments: 0\n  no-with: 2\n  radix: 2\n  vars-on-top: 0\n  wrap-iife: 2\n  yoda: 0\n\n  # Strict\n  strict: 0\n\n  # Variables\n  init-declarations: 0\n  no-catch-shadow: 2\n  no-delete-var: 2\n  no-label-var: 2\n  no-shadow-restricted-names: 2\n  no-shadow: 0\n  no-undef-init: 2\n  no-undef: 0\n  no-undefined: 0\n  no-unused-vars: 0\n  no-use-before-define: 0\n\n  # Node.js and CommonJS\n  callback-return: 2\n  handle-callback-err: 2\n  no-mixed-requires: 0\n  no-new-require: 0\n  no-path-concat: 2\n  no-process-exit: 2\n  no-restricted-modules: 0\n  no-sync: 0\n\n  # Stylistic Issues\n  array-bracket-spacing: 0\n  block-spacing: 0\n  brace-style: 0\n  camelcase: 0\n  comma-spacing: 0\n  comma-style: 0\n  computed-property-spacing: 0\n  consistent-this: 0\n  eol-last: 0\n  func-names: 0\n  func-style: 0\n  id-length: 0\n  id-match: 0\n  indent: 0\n  jsx-quotes: 0\n  key-spacing: 0\n  linebreak-style: 0\n  lines-around-comment: 0\n  max-depth: 0\n  max-len: 0\n  max-nested-callbacks: 0\n  max-params: 0\n  max-statements: [2, 30]\n  new-cap: 0\n  new-parens: 0\n  newline-after-var: 0\n  no-array-constructor: 0\n  no-bitwise: 0\n  no-continue: 0\n  no-inline-comments: 0\n  no-lonely-if: 0\n  no-mixed-spaces-and-tabs: 0\n  no-multiple-empty-lines: 0\n  no-negated-condition: 0\n  no-nested-ternary: 0\n  no-new-object: 0\n  no-plusplus: 0\n  no-restricted-syntax: 0\n  no-spaced-func: 0\n  no-ternary: 0\n  no-trailing-spaces: 0\n  no-underscore-dangle: 0\n  no-unneeded-ternary: 0\n  object-curly-spacing: 0\n  one-var: 0\n  operator-assignment: 0\n  operator-linebreak: 0\n  padded-blocks: 0\n  quote-props: 0\n  quotes: 0\n  require-jsdoc: 0\n  semi-spacing: 0\n  semi: 0\n  sort-vars: 0\n  space-after-keywords: 0\n  space-before-blocks: 0\n  space-before-function-paren: 0\n  space-before-keywords: 0\n  space-in-parens: 0\n  space-infix-ops: 0\n  space-return-throw-case: 0\n  space-unary-ops: 0\n  spaced-comment: 0\n  wrap-regex: 0\n\n  # ECMAScript 6\n  arrow-body-style: 0\n  arrow-parens: 0\n  arrow-spacing: 0\n  constructor-super: 0\n  generator-star-spacing: 0\n  no-arrow-condition: 0\n  no-class-assign: 0\n  no-const-assign: 0\n  no-dupe-class-members: 0\n  no-this-before-super: 0\n  no-var: 0\n  object-shorthand: 0\n  prefer-arrow-callback: 0\n  prefer-const: 0\n  prefer-reflect: 0\n  prefer-spread: 0\n  prefer-template: 0\n  require-yield: 0\n"
  },
  {
    "path": ".gitignore",
    "content": "################################################\n## Dependencies\n################################################\nnode_modules\n\n################################################\n## Nodejs Common Files\n################################################\nlib-cov\n*.seed\n*.log\n*.out\n*.pid\nnpm-debug.log\n\n################################################\n## Secret\n################################################\n.key.json\n\n################################################\n# Miscellaneous\n################################################\n*~\n*#\n.DS_STORE\n.netbeans\nnbproject\n.idea\n.node_history\n\n################################################\n## Instanbul Code Coverage Reports\n################################################\ncoverage\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: node_js\nnode_js:\n  - \"6.10\"\n  - \"6.9\"\n  - \"4.8\"\n  - \"4.4.1\"\n  - \"4.2\"\naddons:\n  code_climate:\n    repo_token: 6131e0b97abea823e9a41cc90736f0c2fdbe5d6b442ce0603f7f131aea6b35c3\nafter_script:\n  - codeclimate-test-reporter < coverage/lcov.info\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2016 Shern Shiou Tan, Alexander Graebe\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README-Nodeback.md",
    "content": "# Initialization\n\nIn order to use this module, you have to import it in your application first:\n\n```javasctipt\nvar Uber = require('node-uber');\n```\n\nNext, initialize the Uber object with the keys you obtained from the [Uber developer dashboard](https://developer.uber.com/dashboard):\n\n```javasctipt\nvar uber = new Uber({\n  client_id: 'CLIENT_ID',\n  client_secret: 'CLIENT_SECRET',\n  server_token: 'SERVER_TOKEN',\n  redirect_uri: 'REDIRECT URL',\n  name: 'APP_NAME',\n  language: 'en_US', // optional, defaults to en_US\n  sandbox: true // optional, defaults to false\n});\n```\n\n> **Note**: For all available `language` options check out the [Localization page of the API](https://developer.uber.com/docs/localization).\n\n# Authenticating\n\nTo make HTTP calls, you need to create an authenticated session with the API. User-specific operations require you to use a OAuth 2 bearer token with specific [scopes](https://developer.uber.com/docs/scopes). Jump to the [method overview section](https://github.com/shernshiou/node-uber#method-overview) to identify required scopes for methods. General operations can use a simple server-token authentication.\n\n## Step one: Authorize\n\nTo obtain an OAuth 2 bearer token, you have to authorize your application with the required scope. Available scopes are: `history`, `history_lite`, `profile`, `request`, `all_trips`, and `places`.\n\nTo do so, you are initially required to redirect your user to an authorization URL. You can generate the authorization URL using `uber.getAuthorizeUrl`. In case you are using [Express](http://expressjs.com/), your route definition could look as follows:\n\n```javascript\napp.get('/api/login', function(request, response) {\n  var url = uber.getAuthorizeUrl(['history','profile', 'request', 'places']);\n  response.redirect(url);\n});\n```\n\nThe URL will lead to a page where your user will be required to login and approve access to his/her Uber account. In case that step was successful, Uber will issue an HTTP 302 redirect to the redirect_uri defined in the [Uber developer dashboard](https://developer.uber.com/dashboard). On that redirect, you will receive an authorization code, which is single use and expires in 10 minutes.\n\n## Step two: Receive redirect and get an access token\n\nTo complete the authorization you now need to receive the callback and convert the given authorization code into an OAuth access token. You can accomplish that using `uber.authorization`. This method will retrieve and store the access_token, refresh_token, authorized scopes, and token expiration date within the uber object for consecutive requests.\n\nUsing Express, you could achieve that as follows:\n\n```javascript\n app.get('/api/callback', function(request, response) {\n    uber.authorization({\n      authorization_code: request.query.code\n    }, function(err, res) {\n      if (err) {\n        console.error(err);\n      } else {\n        // store the user id and associated properties:\n        // access_token = res[0], refresh_token = res[1], scopes = res[2]),and token expiration date = res[3]\n        console.log('New access_token retrieved: ' + res[0]);\n        console.log('... token allows access to scopes: ' + res[2]);\n        console.log('... token is valid until: ' + res[3]);\n        console.log('... after token expiration, re-authorize using refresh_token: ' + res[1]);\n\n        // redirect the user back to your actual app\n        response.redirect('/web/index.html');\n      }\n    });\n});\n```\n\n## Step three: Make HTTP requests to available resources\n\nNow that you are authenticated, you can issue requests using provided methods.\n\nFor instance, to obtain a list of available Uber products for a specific location, you can use `uber.products.getAllForLocation`.\n\nIn case you are using Express, your route definition could look as follows:\n\n```javascript\napp.get('/api/products', function(request, response) {\n  // extract the query from the request URL\n  var query = url.parse(request.url, true).query;\n\n  // if no query params sent, respond with Bad Request\n  if (!query || !query.lat || !query.lng) {\n    response.sendStatus(400);\n  } else {\n    uber.products.getAllForLocation(query.lat, query.lng, function(err, res) {\n      if (err) {\n        console.error(err);\n        response.sendStatus(500);\n      } else {\n        response.json(res);\n      }\n    });\n  }\n});\n```\n\n### Optional: Revoke user access (token)\n\nIf your users decide to disconnect or revoke access to their Uber accounts, you can use the `uber.revokeToken` method. This will invalidate either `access_token` or `refresh_token`. Note that per [RFC7009](https://tools.ietf.org/html/rfc7009), revoke will return success for any string you pass into the function provided the client_id and client_secret are correct. This includes previously revoked tokens and invalid tokens.\n\n```javascript\nuber.revokeToken('My_access_token');\n```\n\n# Method Overview\n\n## [Riders API](https://developer.uber.com/docs/riders/introduction)\n\nHTTP Method | Endpoint                          | Auth Method           | Required Scope                                 | Methods\n----------- | --------------------------------- | --------------------- | ---------------------------------------------- | ---------------------------------------\nGET         | /v1.2/products                      | OAuth or server_token |                                                | products.getAllForAddress\nGET         | /v1.2/products                      | OAuth or server_token |                                                | products.getAllForLocation\nGET         | /v1.2/products/{product_id}         | OAuth or server_token |                                                | products.getByID\nPUT         | /v1.2/sandbox/products/{product_id} | OAuth or server_token | (Sandbox mode)                                 | products.setSurgeMultiplierByID\nPUT         | /v1.2/sandbox/products/{product_id} | OAuth or server_token | (Sandbox mode)                                 | products.setDriversAvailabilityByID\nGET         | /v1.2/estimates/price               | OAuth or server_token |                                                | estimates.getPriceForRoute\nGET         | /v1.2/estimates/price               | OAuth or server_token |                                                | estimates.getPriceForRouteByAddress\nGET         | /v1.2/estimates/time                | OAuth or server_token |                                                | estimates.getETAForAddress\nGET         | /v1.2/estimates/time                | OAuth or server_token |                                                | estimates.getETAForLocation\nGET         | /v1.2/history                       | OAuth                 | history or history_lite                        | user.getHistory\nGET         | /v1.2/me                            | OAuth                 | profile                                        | user.getProfile\nPATCH       | /v1.2/me                            | OAuth                 | profile                                        | user.applyPromo\nPOST        | /v1.2/requests                      | OAuth                 | request (privileged)                           | requests.create\nGET         | /v1.2/requests/current              | OAuth                 | request (privileged) or all_trips (privileged) | requests.getCurrent\nPATCH       | /v1.2/requests/current              | OAuth                 | request (privileged)                           | requests.updateCurrent\nDELETE      | /v1.2/requests/current              | OAuth                 | request (privileged)                           | requests.deleteCurrent\nPOST        | /v1.2/requests/estimate             | OAuth                 | request (privileged)                           | requests.getEstimates\nGET         | /v1.2/requests/{request_id}         | OAuth                 | request (privileged)                           | requests.getByID\nPATCH       | /v1.2/requests/{request_id}         | OAuth                 | request (privileged)                           | requests.updateByID\nPUT         | /v1.2/sandbox/requests/{request_id} | OAuth                 | request (privileged & Sandbox mode )           | requests.setStatusByID\nDELETE      | /v1.2/requests/{request_id}         | OAuth                 | request (privileged)                           | requests.deleteByID\nGET         | /v1.2/requests/{request_id}/map     | OAuth                 | request (privileged)                           | requests.getMapByID\nGET         | /v1.2/requests/{request_id}/receipt | OAuth                 | request_receipt (privileged)                   | requests.getReceiptByID\nGET         | /v1.2/places/{place_id}             | OAuth                 | places                                         | places.getHome and places.getWork\nPUT         | /v1.2/places/{place_id}             | OAuth                 | places                                         | places.updateHome and places.updateWork\nGET         | /v1.2/payment-methods                | OAuth                 | request (privileged)                           | payment.getMethods\n\n## [Drivers API](https://developer.uber.com/docs/drivers)\n\nHTTP Method | Endpoint           | Auth Method | Required Scope   | Methods\n----------- | ------------------ | ----------- | ---------------- | ---------------------------\nGET         | /v1/partners/me       | OAuth       | partner.accounts | partnerprofile.getProfile\nGET         | /v1/partners/payments | OAuth       | partner.payments | partnerpayments.getPayments\nGET         | /v1/partners/trips    | OAuth       | partner.trips    | partnertrips.getTrips\n# Endpoint Details\n\n## Authorization (OAuth 2.0)\n\n### Generate Authorize URL\n\nAfter getting the authorize url, the user will be redirected to the redirect url with authorization code used in the next function.\n\n```javascript\nuber.getAuthorizeUrl(parameter);\n```\n\n#### Parameter\n\n- Array of scopes\n\n#### Example\n\n```javascript\nuber.getAuthorizeUrl(['history','profile', 'request', 'places']);\n```\n\n### Authorize\n\nUsed to convert authorization code or refresh token into access token.\n\n```javascript\nuber.authorization(parameter, callback);\n```\n\n#### Parameter\n\n- JS Object with attribute `authorization_code` OR `refresh_token`\n\n#### Example\n\n> _Note:_ The callback return parameters changed with v1.0.0! This change was necessary to introduce promise-based callbacks.\n\n> ```javascript\n> uber.authorization({ refresh_token: 'REFRESH_TOKEN' },\n>   function (err, res) {\n>     if (err) console.error(err);\n>     else {\n>       // store the user id and associated properties:\n>       // access_token = res[0], refresh_token = res[1], scopes = res[2]),and token expiration date = res[3]\n>       console.log('New access_token retrieved: ' + res[0]);\n>       console.log('... token allows access to scopes: ' + res[2]);\n>       console.log('... token is valid until: ' + res[3]);\n>       console.log('... after token expiration, re-authorize using refresh_token: ' + res[1]);\n>     }\n>   });\n> ```\n\n## /products\n\nThe product endpoint can be accessed either with an OAuth `access_token` or simply with the `server_token` because it is not user-specific. It has, therefore, no required scope for access.\n\n### [Get available products for address](https://developer.uber.com/docs/v1-products)\n\nThis method utilizes [geocoder](https://github.com/wyattdanger/geocoder) to retrieve the coordinates for an address using Google as the provider. It uses the first element of the response. In other words, the coordinates represent what the Google algorithm provides with most confidence value.\n\n> **Note**: To ensure correct coordinates you should provide the complete address, including city, ZIP code, state, and country.\n\n```javascript\nuber.products.getAllForAddress(address, callback);\n```\n\n#### Example\n\n```javascript\nuber.products.getAllForAddress('1455 Market St, San Francisco, CA 94103, US', function (err, res) {\n  if (err) console.error(err);\n  else console.log(res);\n});\n```\n\n### [Get available products for location](https://developer.uber.com/docs/v1-products)\n\n```javascript\nuber.products.getAllForLocation(latitude, longitude, callback);\n```\n\n#### Example\n\n```javascript\nuber.products.getAllForLocation(3.1357169, 101.6881501, function (err, res) {\n  if (err) console.error(err);\n  else console.log(res);\n});\n```\n\n### [Get product details by product_id](https://developer.uber.com/docs/v1-products-details)\n\n```javascript\nuber.products.getByID(product_id, callback);\n```\n\n#### Example\n\n```javascript\nuber.products.getByID('d4abaae7-f4d6-4152-91cc-77523e8165a4', function (err, res) {\n  if (err) console.error(err);\n  else console.log(res);\n});\n```\n\n### [Set driver's availability by product_id](https://developer.uber.com/docs/sandbox)\n\n```javascript\nuber.products.setDriversAvailabilityByID(product_id, availability, callback);\n```\n\n> **Note**: This method is only allowed in Sandbox mode.\n\n#### Parameter\n\n- availability (boolean) will force requests to return a `no_drivers_available` error if set to false\n\n#### Example\n\n```javascript\nuber.products.setDriversAvailabilityByID('d4abaae7-f4d6-4152-91cc-77523e8165a4', false, function (err, res) {\n  if (err) console.error(err);\n  else console.log(res);\n});\n```\n\n### [Set surge multiplier by product_id](https://developer.uber.com/docs/sandbox)\n\n```javascript\nuber.products.setSurgeMultiplierByID(product_id, multiplier, callback);\n```\n\n> **Note**: This method is only allowed in Sandbox mode.\n\n#### Parameter\n\n- multiplier (float) will force two stage confirmation for requests if > 2.0\n\n#### Example\n\n```javascript\nuber.products.setSurgeMultiplierByID('d4abaae7-f4d6-4152-91cc-77523e8165a4', 2.2, function (err, res) {\n  if (err) console.error(err);\n  else console.log(res);\n});\n```\n\n## /estimates\n\nThe estimates endpoint can be accessed either with an OAuth `access_token` or simply with the `server_token` because it is not user-specific. It has, therefore, no required scope for access.\n\n### [Get price estimates for specific address](https://developer.uber.com/docs/v1-estimates-price)\n\nThis method utilizes [geocoder](https://github.com/wyattdanger/geocoder) to retrieve the coordinates for an address using Google as the provider. It uses the first element of the response. In other words, the coordinates represent what the Google algorithm provides with most confidence value.\n\n> **Note**: To ensure correct coordinates you should provide the complete address, including city, ZIP code, state, and country.\n\n> ```javascript\n> uber.estimates.getPriceForRouteByAddress(start_address, end_address, [, seats], callback);\n> ```\n\n`seats` defaults to 2, which is also the maximum value for this parameter.\n\n#### Example\n\n```javascript\nuber.estimates.getPriceForRouteByAddress(\n  '1455 Market St, San Francisco, CA 94103, US',\n  '2675 Middlefield Rd, Palo Alto, CA 94306, US',\n  function (err, res) {\n  if (err) console.error(err);\n  else console.log(res);\n});\n```\n\n### [Get price estimates for specific route](https://developer.uber.com/docs/v1-estimates-price)\n\n```javascript\nuber.estimates.getPriceForRoute(start_latitude, start_longitude, end_latitude, end_longitude [, seats], callback);\n```\n\n`seats` defaults to 2, which is also the maximum value for this parameter.\n\n#### Example\n\n```javascript\nuber.estimates.getPriceForRoute(3.1357169, 101.6881501, 3.0833, 101.6500, function (err, res) {\n  if (err) console.error(err);\n  else console.log(res);\n});\n```\n\n### [Get ETA for address](https://developer.uber.com/docs/v1-estimates-time)\n\nThis method utilizes [geocoder](https://github.com/wyattdanger/geocoder) to retrieve the coordinates for an address using Google as the provider. It uses the first element of the response. In other words, the coordinates represent what the Google algorithm provides with most confidence value.\n\n> **Note**: To ensure correct coordinates you should provide the complete address, including city, ZIP code, state, and country.\n\n```javascript\nuber.estimates.getETAForAddress(address, [, product_id], callback);\n```\n\n#### Example\n\n```javascript\nuber.estimates.getETAForAddress('455 Market St, San Francisco, CA 94103, US', function (err, res) {\n  if (err) console.error(err);\n  else console.log(res);\n});\n```\n\n### [Get ETA for location](https://developer.uber.com/docs/v1-estimates-time)\n\n```javascript\nuber.estimates.getETAForLocation(latitude, longitude [, product_id], callback);\n```\n\n#### Example\n\n```javascript\nuber.estimates.getETAForLocation(3.1357169, 101.6881501, function (err, res) {\n  if (err) console.error(err);\n  else console.log(res);\n});\n```\n\n## /history\n\nThe history endpoint can be accessed ONLY with an OAuth `access_token` authorized with either the `history` or `history_lite` (without city information) scope.\n\n### [Get user activity](https://developer.uber.com/docs/v12-history)\n\n```javascript\nuber.user.getHistory(offset, limit, callback);\n```\n\n`offset` defaults to 0 and `limit` defaults to 5 with a maximum value of 50.\n\n#### Example\n\n```javascript\nuber.user.getHistory(0, 5, function(err, res) {\n  if (err) console.log(err);\n  else console.log(res);\n});\n```\n\n## /me\n\nThe me endpoint can be accessed ONLY with an OAuth `access_token` authorized with the `profile` scope.\n\n### [Get user profile](https://developer.uber.com/docs/v1-me)\n\n```javascript\nuber.user.getProfile(callback);\n```\n\n#### Example\n\n```javascript\nuber.user.getProfile(function (err, res) {\n  if (err) console.log(err);\n  else console.log(res);\n});\n```\n\n#### [Apply promo code to user account](https://developer.uber.com/docs/riders/references/api/v1.2/me-patch)\n\n```javascript\nuber.user.applyPromo(code);\n```\n\n##### Parameter\n\n- user promotion code (string)\n\n##### Example\n\n```javascript\nuber.user.applyPromo('FREE_RIDEZ', function (err, res) {\n  if (err) console.log(err);\n  else console.log(res);\n});\n```\n\n## /requests\n\nThe requests endpoint can be accessed ONLY with an OAuth `access_token` authorized with the `request` scope.\n\n### [Create new request](https://developer.uber.com/docs/v1-requests)\n\n```javascript\nuber.requests.create(parameter, callback);\n```\n\n#### Parameter\n\n- JS Object with at least the following attributes:\n  - `start_latitude` & `start_longitude` OR `start_place_id`\n  - `end_latitude` & `end_longitude` OR `end_place_id`\n  -  The key for the upfront fare of a ride (`fare_id`)\n- You can provide `startAddress` instead of `start_latitude` & `start_longitude` and `endAddress` instead of `end_latitude` & `end_longitude` thanks to [geocoder](https://github.com/wyattdanger/geocoder)\n\n> **Note**: To ensure correct coordinates you should provide the complete address, including city, ZIP code, state, and country.\n\n#### Example\n\n```javascript\nuber.requests.create({\n  \"fare_id\": \"d30e732b8bba22c9cdc10513ee86380087cb4a6f89e37ad21ba2a39f3a1ba960\",\n  \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n  \"start_latitude\": 37.761492,\n  \"start_longitude\": -122.423941,\n  \"end_latitude\": 37.775393,\n  \"end_longitude\": -122.417546\n}, function (err, res) {\n  if (err) console.error(err);\n  else console.log(res);\n});\n```\n\n### [Get current request](https://developer.uber.com/docs/v1-requests-current)\n\n> **Note**: By default, only details about trips your app requested will be returned. This endpoint can be used with the scope `all_trips` to get all trips irrespective of which application initiated them.\n\n```javascript\nuber.requests.getCurrent(callback);\n```\n\n#### Example\n\n```javascript\nuber.requests.getCurrent(function (err, res) {\n  if (err) console.log(err);\n  else console.log(res);\n});\n```\n\n### [Update current request](https://developer.uber.com/docs/v1-requests-current-patch)\n\n```javascript\nuber.requests.updateCurrent(parameter, callback);\n```\n\n#### Parameter\n\n- JS Object with attributes to be updated (only destination-related attributes enabled)\n- You can provide `startAddress` instead of `start_latitude` & `start_longitude` and `endAddress` instead of `end_latitude` & `end_longitude` thanks to [geocoder](https://github.com/wyattdanger/geocoder)\n\n> **Note**: To ensure correct coordinates you should provide the complete address, including city, ZIP code, state, and country.\n\n#### Example\n\n```javascript\nuber.requests.updateCurrent({\n  \"end_latitude\": 37.775393,\n  \"end_longitude\": -122.417546\n}, function (err, res) {\n  if (err) console.error(err);\n  else console.log(res);\n});\n```\n\n### [Delete current request](https://developer.uber.com/docs/v1-requests-current-delete)\n\n```javascript\nuber.requests.deleteCurrent(callback);\n```\n\n#### Example\n\n```javascript\nuber.requests.deleteCurrent(function (err, res) {\n  if (err) console.log(err);\n  else console.log(res);\n});\n```\n\n### [Get estimates](https://developer.uber.com/docs/v1-requests-estimate)\n\n```javascript\nuber.requests.getEstimates(parameter, callback);\n```\n\n#### Parameter\n\n- JS Object with at least the following attributes:\n  - `start_latitude` & `start_longitude` OR `start_place_id`\n  - `end_latitude` & `end_longitude` OR `end_place_id`\n- You can provide `startAddress` instead of `start_latitude` & `start_longitude` and `endAddress` instead of `end_latitude` & `end_longitude` thanks to [geocoder](https://github.com/wyattdanger/geocoder)\n\n> **Note**: To ensure correct coordinates you should provide the complete address, including city, ZIP code, state, and country.\n\n#### Example\n\n```javascript\nuber.requests.getEstimates({\n  \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n  \"start_latitude\": 37.761492,\n  \"start_longitude\": -122.423941,\n  \"end_latitude\": 37.775393,\n  \"end_longitude\": -122.417546\n}, function (err, res) {\n  if (err) console.error(err);\n  else console.log(res);\n});\n```\n\n### [Get request by request_id](https://developer.uber.com/docs/v1-requests-details)\n\n```javascript\nuber.requests.getByID(request_id, callback);\n```\n\n#### Example\n\n```javascript\nuber.requests.getByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', function (err, res) {\n  if (err) console.log(err);\n  else console.log(res);\n});\n```\n\n### [Update request by request_id](https://developer.uber.com/docs/v1-requests-patch)\n\n```javascript\nuber.requests.updateByID(request_id, parameter, callback);\n```\n\n#### Parameter\n\n- JS Object with attributes to be updated (only destination-related attributes enabled)\n- You can provide `startAddress` instead of `start_latitude` & `start_longitude` and `endAddress` instead of `end_latitude` & `end_longitude` thanks to [geocoder](https://github.com/wyattdanger/geocoder)\n\n> **Note**: To ensure correct coordinates you should provide the complete address, including city, ZIP code, state, and country.\n\n#### Example\n\n```javascript\nuber.requests.updateByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', {\n  \"end_latitude\": 37.775393,\n  \"end_longitude\": -122.417546\n}, function (err, res) {\n  if (err) console.error(err);\n  else console.log(res);\n});\n```\n\n### [Set request status by request_id](https://developer.uber.com/docs/sandbox)\n\n```javascript\nuber.requests.setStatusByID(request_id, status, callback);\n```\n\n> **Note**: This method is only allowed in Sandbox mode. Check out the [documentation](https://developer.uber.com/docs/sandbox) for valid status properties.\n\n#### Example\n\n```javascript\nuber.requests.setStatusByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', 'accepted', function (err, res) {\n  if (err) console.error(err);\n  else console.log(res);\n});\n```\n\n### [Delete request by request_id](https://developer.uber.com/docs/v1-requests-cancel)\n\n```javascript\nuber.requests.deleteByID(request_id, callback);\n```\n\n#### Example\n\n```javascript\nuber.requests.deleteByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', function (err, res) {\n  if (err) console.log(err);\n  else console.log(res);\n});\n```\n\n### [Get request map by request_id](https://developer.uber.com/docs/v1-requests-map)\n\n```javascript\nuber.requests.getMapByID(request_id, callback);\n```\n\nUnless the referenced request is in status `accepted`, a 404 error will be returned.\n\n#### Example\n\n```javascript\nuber.requests.getMapByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', function (err, res) {\n  if (err) console.log(err);\n  else console.log(res);\n});\n```\n\n### [Get request receipt by request_id](https://developer.uber.com/docs/v1-requests-receipt)\n\n> **Note**: This endpoint requires OAuth authentication with the scope `request_receipt`\n\n```javascript\nuber.requests.getReceiptByID(request_id, callback);\n```\n\nThe referenced request must be in status `completed`.\n\n#### Example\n\n```javascript\nuber.requests.getReceiptByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', function (err, res) {\n  if (err) console.log(err);\n  else console.log(res);\n});\n```\n\n## /places\n\nThe places endpoint can be accessed ONLY with an OAuth `access_token` authorized with the `places` scope.\n\n> **Note**: As of right now, only two place_ids are allowed: `home` and `work`.\n\n### [Get home address](https://developer.uber.com/docs/v1-places-get)\n\n```javascript\nuber.places.getHome(callback);\n```\n\n#### Example\n\n```javascript\nuber.places.getHome(function (err, res) {\n  if (err) console.log(err);\n  else console.log(res);\n});\n```\n\n### [Get work address](https://developer.uber.com/docs/v1-places-get)\n\n```javascript\nuber.places.getWork(callback);\n```\n\n#### Example\n\n```javascript\nuber.places.getWork(function (err, res) {\n  if (err) console.log(err);\n  else console.log(res);\n});\n```\n\n### [Update home address](https://developer.uber.com/docs/v1-places-put)\n\n```javascript\nuber.places.updateHome(address, callback);\n```\n\n#### Example\n\n```javascript\nuber.places.updateHome('685 Market St, San Francisco, CA 94103, USA', function (err, res) {\n  if (err) console.log(err);\n  else console.log(res);\n});\n```\n\n### [Update work address](https://developer.uber.com/docs/v1-places-put)\n\n```javascript\nuber.places.updateWork(address, callback);\n```\n\n#### Example\n\n```javascript\nuber.places.updateWork('1455 Market St, San Francisco, CA 94103, USA', function (err, res) {\n  if (err) console.log(err);\n  else console.log(res);\n});\n```\n\n## /payment-methods\n\nThe payment-methods endpoint can be accessed ONLY with an OAuth `access_token` authorized with the `request` scope.\n\n### [Get available payment methods](https://developer.uber.com/docs/v1-payment-methods)\n\n```javascript\nuber.payment.getMethods(callback);\n```\n\n#### Example\n\n```javascript\nuber.payment.getMethods(function (err, res) {\n  if (err) console.log(err);\n  else console.log(res);\n});\n```\n\n## /partners\n\nThe partners endpoints (Driver API) can be accessed ONLY with an OAuth `access_token` authorized with [the respective scopes](https://developer.uber.com/docs/drivers/guides/scopes) (`partner.accounts`, `partner.trips`, or `partner.payments`).\n\n### [Get driver profile](https://developer.uber.com/docs/drivers/references/api/v1/partners-me-get)\n\n```javascript\nuber.partnerprofile.getProfile(callback);\n```\n\n#### Example\n\n```javascript\nuber.partnerprofile.getProfile(function (err, res) {\n  if (err) console.log(err);\n  else console.log(res);\n});\n```\n\n### [Get driver payments](https://developer.uber.com/docs/drivers/references/api/v1/partners-payments-get)\n\n```javascript\nuber.partnerpayments.getPayments(offset, limit, from_time, to_time, callback);\n```\n\n##### Parameter\n\n- offset for payments list (sorted by creation time). Defaults to `0`\n- limit of payments list. Defaults to `5`\n- minimum Unix timestamp for filtered payments list\n- maximum Unix timestamp for filtered payments list\n\n#### Example\n\n```javascript\nuber.partnerpayments.getPayments(0, 50, 1451606400, 1505160819, function (err, res) {\n  if (err) console.log(err);\n  else console.log(res);\n});\n```\n\n### [Get driver trips](https://developer.uber.com/docs/drivers/references/api/v1/partners-trips-get)\n\n```javascript\nuber.partnertrips.getTrips(offset, limit, from_time, to_time, callback);\n```\n\n##### Parameter\n\n- offset for trips list (sorted by creation time). Defaults to `0`\n- limit of trips list. Defaults to `5`\n- minimum Unix timestamp for filtered trips list\n- maximum Unix timestamp for filtered trips list\n\n#### Example\n\n```javascript\nuber.partnertrips.getTrips(0, 50, 1451606400, 1505160819, function (err, res) {\n  if (err) console.log(err);\n  else console.log(res);\n});\n```\n"
  },
  {
    "path": "README.md",
    "content": "[![Join the chat at https://gitter.im/shernshiou/node-uber](https://badges.gitter.im/shernshiou/node-uber.svg)](https://gitter.im/shernshiou/node-uber?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![License](http://img.shields.io/:license-mit-blue.svg)](http://doge.mit-license.org) [![build status](https://img.shields.io/travis/shernshiou/node-uber.svg?style=flat-square)](https://travis-ci.org/shernshiou/node-uber) [![Dependency Status](https://david-dm.org/shernshiou/node-uber.svg?style=flat-square)](https://david-dm.org/shernshiou/node-uber) [![devDependency Status](https://david-dm.org/shernshiou/node-uber/dev-status.svg)](https://david-dm.org/shernshiou/node-uber#info=devDependencies) [![Code Climate](https://codeclimate.com/github/shernshiou/node-uber/badges/gpa.svg)](https://codeclimate.com/github/shernshiou/node-uber) [![Test Coverage](https://codeclimate.com/github/shernshiou/node-uber/badges/coverage.svg)](https://codeclimate.com/github/shernshiou/node-uber/coverage)\n\n# Uber Rides Node.js Wrapper\n\nThis projects helps you to make HTTP requests to the Uber Rides API.\n\n## Installation\n\nBefore you begin, you need to register your app in the [Uber developer dashboard](https://developer.uber.com/dashboard). Notice that the app gets a client ID, secret, and server token required for authenticating with the API.\n\nAfter registering your application, you need to install this module in your Node.js project:\n\n```sh\nnpm install node-uber\n```\n\n## Initialization\n\nIn order to use this module, you have to import it in your application first:\n\n```javasctipt\nvar Uber = require('node-uber');\n```\n\nNext, initialize the Uber object with the keys you obtained from the [Uber developer dashboard](https://developer.uber.com/dashboard):\n\n```javasctipt\nvar uber = new Uber({\n  client_id: 'CLIENT_ID',\n  client_secret: 'CLIENT_SECRET',\n  server_token: 'SERVER_TOKEN',\n  redirect_uri: 'REDIRECT URL',\n  name: 'APP_NAME',\n  language: 'en_US', // optional, defaults to en_US\n  sandbox: true, // optional, defaults to false\n  proxy: 'PROXY URL' // optional, defaults to none\n});\n```\n\n> **Note**: For all available `language` options check out the [Localization page of the API](https://developer.uber.com/docs/localization).\n\n## Authenticating\n\nTo make HTTP calls, you need to create an authenticated session with the API. User-specific operations require you to use a OAuth 2 bearer token with specific [scopes](https://developer.uber.com/docs/scopes). Jump to the [method overview section](https://github.com/shernshiou/node-uber#method-overview) to identify required scopes for methods. General operations can use a simple server-token authentication.\n\n### Step one: Authorize\n\nTo obtain an OAuth 2 bearer token, you have to authorize your application with the required scope. Available scopes are: `history`, `history_lite`, `profile`, `request`, `all_trips`, and `places`.\n\nTo do so, you are initially required to redirect your user to an authorization URL. You can generate the authorization URL using `uber.getAuthorizeUrl`. In case you are using [Express](http://expressjs.com/), your route definition could look as follows:\n\n```javascript\napp.get('/api/login', function(request, response) {\n  var url = uber.getAuthorizeUrl(['history','profile', 'request', 'places']);\n  response.redirect(url);\n});\n```\n\nThe URL will lead to a page where your user will be required to login and approve access to his/her Uber account. In case that step was successful, Uber will issue an HTTP 302 redirect to the redirect_uri defined in the [Uber developer dashboard](https://developer.uber.com/dashboard). On that redirect, you will receive an authorization code, which is single use and expires in 10 minutes.\n\n### Step two: Receive redirect and get an access token\n\nTo complete the authorization you now need to receive the callback and convert the given authorization code into an OAuth access token. You can accomplish that using `uber.authorizationAsync`. This method will retrieve and store the access_token, refresh_token, authorized scopes, and token expiration date within the uber object for consecutive requests.\n\nUsing Express, you could achieve that as follows:\n\n```javascript\n app.get('/api/callback', function(request, response) {\n    uber.authorizationAsync({authorization_code: request.query.code})\n    .spread(function(access_token, refresh_token, authorizedScopes, tokenExpiration) {\n      // store the user id and associated access_token, refresh_token, scopes and token expiration date\n      console.log('New access_token retrieved: ' + access_token);\n      console.log('... token allows access to scopes: ' + authorizedScopes);\n      console.log('... token is valid until: ' + tokenExpiration);\n      console.log('... after token expiration, re-authorize using refresh_token: ' + refresh_token);\n\n      // redirect the user back to your actual app\n      response.redirect('/web/index.html');\n    })\n    .error(function(err) {\n      console.error(err);\n    });\n});\n```\n\n> **Nodeback**: Looking for nodeback-style methods? Check out the [nodeback-readme](README-Nodeback.md).\n\n### Step three: Make HTTP requests to available resources\n\nNow that you are authenticated, you can issue requests using provided methods.\n\nFor instance, to obtain a list of available Uber products for a specific location, you can use `uber.products.getAllForLocationAsync`.\n\nIn case you are using Express, your route definition could look as follows:\n\n```javascript\napp.get('/api/products', function(request, response) {\n  // extract the query from the request URL\n  var query = url.parse(request.url, true).query;\n\n  // if no query params sent, respond with Bad Request\n  if (!query || !query.lat || !query.lng) {\n    response.sendStatus(400);\n  } else {\n    uber.products.getAllForLocationAsync(query.lat, query.lng)\n    .then(function(res) {\n        response.json(res);\n    })\n    .error(function(err) {\n      console.error(err);\n      response.sendStatus(500);\n    });\n  }\n});\n```\n\n### Optional: Revoke user access (token)\n\nIf your users decide to disconnect or revoke access to their Uber accounts, you can use the `uber.revokeTokenAsync` method. This will invalidate either `access_token` or `refresh_token`. Note that per [RFC7009](https://tools.ietf.org/html/rfc7009), revoke will return success for any string you pass into the function provided the client_id and client_secret are correct. This includes previously revoked tokens and invalid tokens.\n\n```javascript\nuber.revokeTokenAsync('My_access_token');\n```\n\n## Method Overview\n\n> **Nodeback**: Looking for nodeback-style methods? Check out the [nodeback-readme](README-Nodeback.md).\n\n## [Riders API](https://developer.uber.com/docs/riders/introduction)\n\nHTTP Method | Endpoint                          | Auth Method           | Required Scope                                 | Methods\n----------- | --------------------------------- | --------------------- | ---------------------------------------------- | -------------------------------------------------\nGET         | /v1.2/products                      | OAuth or server_token |                                                | products.getAllForAddressAsync\nGET         | /v1.2/products                      | OAuth or server_token |                                                | products.getAllForLocationAsync\nGET         | /v1.2/products/{product_id}         | OAuth or server_token |                                                | products.getByIDAsync\nPUT         | /v1.2/sandbox/products/{product_id} | OAuth or server_token | (Sandbox mode)                                 | products.setSurgeMultiplierByIDAsync\nPUT         | /v1.2/sandbox/products/{product_id} | OAuth or server_token | (Sandbox mode)                                 | products.setDriversAvailabilityByIDAsync\nGET         | /v1.2/estimates/price               | OAuth or server_token |                                                | estimates.getPriceForRouteAsync\nGET         | /v1.2/estimates/price               | OAuth or server_token |                                                | estimates.getPriceForRouteByAddressAsync\nGET         | /v1.2/estimates/time                | OAuth or server_token |                                                | estimates.getETAForAddressAsync\nGET         | /v1.2/estimates/time                | OAuth or server_token |                                                | estimates.getETAForLocationAsync\nGET         | /v1.2/history                     | OAuth                 | history or history_lite                        | user.getHistoryAsync\nGET         | /v1.2/me                            | OAuth                 | profile                                        | user.getProfileAsync\nPATCH       | /v1.2/me                          | OAuth                 | profile                                        | user.applyPromoAsync\nPOST        | /v1.2/requests                      | OAuth                 | request (privileged)                           | requests.createAsync\nGET         | /v1.2/requests/current              | OAuth                 | request (privileged) or all_trips (privileged) | requests.getCurrentAsync\nPATCH       | /v1.2/requests/current              | OAuth                 | request (privileged)                           | requests.updateCurrentAsync\nDELETE      | /v1.2/requests/current              | OAuth                 | request (privileged)                           | requests.deleteCurrentAsync\nPOST        | /v1.2/requests/estimate             | OAuth                 | request (privileged)                           | requests.getEstimatesAsync\nGET         | /v1.2/requests/{request_id}         | OAuth                 | request (privileged)                           | requests.getByIDAsync\nPATCH       | /v1.2/requests/{request_id}         | OAuth                 | request (privileged)                           | requests.updateByIDAsync\nPUT         | /v1.2/sandbox/requests/{request_id} | OAuth                 | request (privileged & Sandbox mode )           | requests.setStatusByIDAsync\nDELETE      | /v1.2/requests/{request_id}         | OAuth                 | request (privileged)                           | requests.deleteByIDAsync\nGET         | /v1.2/requests/{request_id}/map     | OAuth                 | request (privileged)                           | requests.getMapByIDAsync\nGET         | /v1.2/requests/{request_id}/receipt | OAuth                 | request_receipt (privileged)                   | requests.getReceiptByIDAsync\nGET         | /v1.2/places/{place_id}             | OAuth                 | places                                         | places.getHomeAsync and places.getWorkAsync\nPUT         | /v1.2/places/{place_id}             | OAuth                 | places                                         | places.updateHomeAsync and places.updateWorkAsync\nGET         | /v1.2/payment-methods                | OAuth                 | request (privileged)                           | payment.getMethodsAsync\n\n## [Drivers API](https://developer.uber.com/docs/drivers)\n\nHTTP Method | Endpoint           | Auth Method | Required Scope   | Methods\n----------- | ------------------ | ----------- | ---------------- | --------------------------------\nGET         | /v1/partners/me       | OAuth       | partner.accounts | partnerprofile.getProfileAsync\nGET         | /v1/partners/payments | OAuth       | partner.payments | partnerpayments.getPaymentsAsync\nGET         | /v1/partners/trips    | OAuth       | partner.trips    | partnertrips.getTripsAsync\n\n## Endpoint Details\n\n### Authorization (OAuth 2.0)\n\n#### Generate Authorize URL\n\nAfter getting the authorize url, the user will be redirected to the redirect url with authorization code used in the next function.\n\n```javascript\nuber.getAuthorizeUrl(parameter);\n```\n\n##### Parameter\n\n- Array of scopes\n\n##### Example\n\n```javascript\nuber.getAuthorizeUrl(['history','profile', 'request', 'places']);\n```\n\n#### Authorize\n\nUsed to convert authorization code or refresh token into access token.\n\n```javascript\nuber.authorizationAsync(parameter);\n```\n\n##### Parameter\n\n- JS Object with attribute `authorization_code` OR `refresh_token`\n\n##### Example: Just access_token\n\n```javascript\nuber.authorizationAsync({ refresh_token: 'REFRESH_TOKEN' })\n  .then(function(access_token) { console.log(access_token); })\n  .error(function(err) { console.error(err); });\n});\n```\n\n##### Example: All properties\n\n```javascript\nuber.authorizationAsync({ refresh_token: 'REFRESH_TOKEN' })\n.spread(function(access_token, refresh_token, authorizedScopes, tokenExpiration) {\n  // store the user id and associated access_token, refresh_token, scopes and token expiration date\n  console.log('New access_token retrieved: ' + access_token);\n  console.log('... token allows access to scopes: ' + authorizedScopes);\n  console.log('... token is valid until: ' + tokenExpiration);\n  console.log('... after token expiration, re-authorize using refresh_token: ' + refresh_token);\n})\n  .error(function(err) { console.error(err); });\n});\n```\n\n### /products\n\nThe product endpoint can be accessed either with an OAuth `access_token` or simply with the `server_token` because it is not user-specific. It has, therefore, no required scope for access.\n\n#### [Get available products for address](https://developer.uber.com/docs/v1-products)\n\nThis method utilizes [geocoder](https://github.com/wyattdanger/geocoder) to retrieve the coordinates for an address using Google as the provider. It uses the first element of the response. In other words, the coordinates represent what the Google algorithm provides with most confidence value.\n\n> **Note**: To ensure correct coordinates you should provide the complete address, including city, ZIP code, state, and country.\n\n```javascript\nuber.products.getAllForAddressAsync(address);\n```\n\n##### Example\n\n```javascript\nuber.products.getAllForAddressAsync('1455 Market St, San Francisco, CA 94103, US')\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Get available products for location](https://developer.uber.com/docs/v1-products)\n\n```javascript\nuber.products.getAllForLocationAsync(latitude, longitude);\n```\n\n##### Example\n\n```javascript\nuber.products.getAllForLocationAsync(3.1357169, 101.6881501)\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Get product details by product_id](https://developer.uber.com/docs/v1-products-details)\n\n```javascript\nuber.products.getByIDAsync(product_id);\n```\n\n##### Example\n\n```javascript\nuber.products.getByIDAsync('d4abaae7-f4d6-4152-91cc-77523e8165a4')\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Set driver's availability by product_id](https://developer.uber.com/docs/sandbox)\n\n```javascript\nuber.products.setDriversAvailabilityByIDAsync(product_id, availability);\n```\n\n> **Note**: This method is only allowed in Sandbox mode.\n\n##### Parameter\n\n- availability (boolean) will force requests to return a `no_drivers_available` error if set to false\n\n##### Example\n\n```javascript\nuber.products.setDriversAvailabilityByIDAsync('d4abaae7-f4d6-4152-91cc-77523e8165a4', false)\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Set surge multiplier by product_id](https://developer.uber.com/docs/sandbox)\n\n```javascript\nuber.products.setSurgeMultiplierByIDAsync(product_id, multiplier);\n```\n\n> **Note**: This method is only allowed in Sandbox mode.\n\n##### Parameter\n\n- multiplier (float) will force two stage confirmation for requests if > 2.0\n\n##### Example\n\n```javascript\nuber.products.setSurgeMultiplierByIDAsync('d4abaae7-f4d6-4152-91cc-77523e8165a4', 2.2)\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n### /estimates\n\nThe estimates endpoint can be accessed either with an OAuth `access_token` or simply with the `server_token` because it is not user-specific. It has, therefore, no required scope for access.\n\n#### [Get price estimates for specific address](https://developer.uber.com/docs/v1-estimates-price)\n\nThis method utilizes [geocoder](https://github.com/wyattdanger/geocoder) to retrieve the coordinates for an address using Google as the provider. It uses the first element of the response. In other words, the coordinates represent what the Google algorithm provides with most confidence value.\n\n> **Note**: To ensure correct coordinates you should provide the complete address, including city, ZIP code, state, and country.\n\n> ```javascript\n> uber.estimates.getPriceForRouteByAddressAsync(start_address, end_address, [, seats]);\n> ```\n\n`seats` defaults to 2, which is also the maximum value for this parameter.\n\n##### Example\n\n```javascript\nuber.estimates.getPriceForRouteByAddressAsync(\n  '1455 Market St, San Francisco, CA 94103, US',\n  '2675 Middlefield Rd, Palo Alto, CA 94306, US')\n  .then(function(res) { console.log(res); })\n  .error(function(err) { console.error(err); });\n```\n\n#### [Get price estimates for specific route](https://developer.uber.com/docs/v1-estimates-price)\n\n```javascript\nuber.estimates.getPriceForRouteAsync(start_latitude, start_longitude, end_latitude, end_longitude [, seats]);\n```\n\n`seats` defaults to 2, which is also the maximum value for this parameter.\n\n##### Example\n\n```javascript\nuber.estimates.getPriceForRouteAsync(3.1357169, 101.6881501, 3.0833, 101.6500)\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Get ETA for address](https://developer.uber.com/docs/v1-estimates-time)\n\nThis method utilizes [geocoder](https://github.com/wyattdanger/geocoder) to retrieve the coordinates for an address using Google as the provider. It uses the first element of the response. In other words, the coordinates represent what the Google algorithm provides with most confidence value.\n\n> **Note**: To ensure correct coordinates you should provide the complete address, including city, ZIP code, state, and country.\n\n```javascript\nuber.estimates.getETAForAddressAsync(address, [, product_id]);\n```\n\n##### Example\n\n```javascript\nuber.estimates.getETAForAddressAsync('455 Market St, San Francisco, CA 94103, US')\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n});\n```\n\n#### [Get ETA for location](https://developer.uber.com/docs/v1-estimates-time)\n\n```javascript\nuber.estimates.getETAForLocationAsync(latitude, longitude [, product_id]);\n```\n\n##### Example\n\n```javascript\nuber.estimates.getETAForLocationAsync(3.1357169, 101.6881501)\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n### /history\n\nThe history endpoint can be accessed ONLY with an OAuth `access_token` authorized with either the `history` or `history_lite` (without city information) scope.\n\n#### [Get user activity](https://developer.uber.com/docs/v12-history)\n\n```javascript\nuber.user.getHistoryAsync(offset, limit);\n```\n\n`offset` defaults to 0 and `limit` defaults to 5 with a maximum value of 50.\n\n##### Example\n\n```javascript\nuber.user.getHistoryAsync(0, 5)\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n### /me\n\nThe me endpoint can be accessed ONLY with an OAuth `access_token` authorized with the `profile` scope.\n\n#### [Get user profile](https://developer.uber.com/docs/v1-me)\n\n```javascript\nuber.user.getProfileAsync();\n```\n\n##### Example\n\n```javascript\nuber.user.getProfileAsync()\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Apply promo code to user account](https://developer.uber.com/docs/riders/references/api/v1.2/me-patch)\n\n```javascript\nuber.user.applyPromoAsync(code);\n```\n\n##### Parameter\n\n- user promotion code (string)\n\n##### Example\n\n```javascript\nuber.user.applyPromoAsync('FREE_RIDEZ')\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n### /requests\n\nThe requests endpoint can be accessed ONLY with an OAuth `access_token` authorized with the `request` scope.\n\n#### [Create new request](https://developer.uber.com/docs/v1-requests)\n\n```javascript\nuber.requests.createAsync(parameter);\n```\n\n##### Parameter\n\n- JS Object with at least the following attributes:\n  - `start_latitude` & `start_longitude` OR `start_place_id`\n  - `end_latitude` & `end_longitude` OR `end_place_id`\n  -  The key for the upfront fare of a ride (`fare_id`)\n- You can provide `startAddress` instead of `start_latitude` & `start_longitude` and `endAddress` instead of `end_latitude` & `end_longitude` thanks to [geocoder](https://github.com/wyattdanger/geocoder)\n\n> **Note**: To ensure correct coordinates you should provide the complete address, including city, ZIP code, state, and country.\n\n##### Example\n\n```javascript\nuber.requests.createAsync({\n  \"fare_id\": \"d30e732b8bba22c9cdc10513ee86380087cb4a6f89e37ad21ba2a39f3a1ba960\",\n  \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n  \"start_latitude\": 37.761492,\n  \"start_longitude\": -122.423941,\n  \"end_latitude\": 37.775393,\n  \"end_longitude\": -122.417546\n})\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Get current request](https://developer.uber.com/docs/v1-requests-current)\n\n> **Note**: By default, only details about trips your app requested will be returned. This endpoint can be used with the scope `all_trips` to get all trips irrespective of which application initiated them.\n\n```javascript\nuber.requests.getCurrentAsync();\n```\n\n##### Example\n\n```javascript\nuber.requests.getCurrentAsync()\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Update current request](https://developer.uber.com/docs/v1-requests-current-patch)\n\n```javascript\nuber.requests.updateCurrentAsync(parameter);\n```\n\n##### Parameter\n\n- JS Object with attributes to be updated (only destination-related attributes enabled)\n- You can provide `startAddress` instead of `start_latitude` & `start_longitude` and `endAddress` instead of `end_latitude` & `end_longitude` thanks to [geocoder](https://github.com/wyattdanger/geocoder)\n\n> **Note**: To ensure correct coordinates you should provide the complete address, including city, ZIP code, state, and country.\n\n##### Example\n\n```javascript\nuber.requests.updateCurrentAsync({\n  \"end_latitude\": 37.775393,\n  \"end_longitude\": -122.417546\n})\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Delete current request](https://developer.uber.com/docs/v1-requests-current-delete)\n\n```javascript\nuber.requests.deleteCurrentAsync();\n```\n\n##### Example\n\n```javascript\nuber.requests.deleteCurrentAsync()\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Get estimates](https://developer.uber.com/docs/v1-requests-estimate)\n\n```javascript\nuber.requests.getEstimatesAsync(parameter);\n```\n\n##### Parameter\n\n- JS Object with at least the following attributes:\n  - `start_latitude` & `start_longitude` OR `start_place_id`\n  - `end_latitude` & `end_longitude` OR `end_place_id`\n- You can provide `startAddress` instead of `start_latitude` & `start_longitude` and `endAddress` instead of `end_latitude` & `end_longitude` thanks to [geocoder](https://github.com/wyattdanger/geocoder)\n\n> **Note**: To ensure correct coordinates you should provide the complete address, including city, ZIP code, state, and country.\n\n##### Example\n\n```javascript\nuber.requests.getEstimatesAsync({\n  \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n  \"start_latitude\": 37.761492,\n  \"start_longitude\": -122.423941,\n  \"end_latitude\": 37.775393,\n  \"end_longitude\": -122.417546\n})\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Get request by request_id](https://developer.uber.com/docs/v1-requests-details)\n\n```javascript\nuber.requests.getByIDAsync(request_id);\n```\n\n##### Example\n\n```javascript\nuber.requests.getByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315')\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Update request by request_id](https://developer.uber.com/docs/v1-requests-patch)\n\n```javascript\nuber.requests.updateByIDAsync(request_id, parameter);\n```\n\n##### Parameter\n\n- JS Object with attributes to be updated (only destination-related attributes enabled)\n- You can provide `startAddress` instead of `start_latitude` & `start_longitude` and `endAddress` instead of `end_latitude` & `end_longitude` thanks to [geocoder](https://github.com/wyattdanger/geocoder)\n\n> **Note**: To ensure correct coordinates you should provide the complete address, including city, ZIP code, state, and country.\n\n##### Example\n\n```javascript\nuber.requests.updateByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315', {\n  \"end_latitude\": 37.775393,\n  \"end_longitude\": -122.417546\n})\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Set request status by request_id](https://developer.uber.com/docs/sandbox)\n\n```javascript\nuber.requests.setStatusByIDAsync(request_id, status);\n```\n\n> **Note**: This method is only allowed in Sandbox mode. Check out the [documentation](https://developer.uber.com/docs/sandbox) for valid status properties.\n\n##### Example\n\n```javascript\nuber.requests.setStatusByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315', 'accepted')\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Delete request by request_id](https://developer.uber.com/docs/v1-requests-cancel)\n\n```javascript\nuber.requests.deleteByIDAsync(request_id);\n```\n\n##### Example\n\n```javascript\nuber.requests.deleteByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315')\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Get request map by request_id](https://developer.uber.com/docs/v1-requests-map)\n\n```javascript\nuber.requests.getMapByIDAsync(request_id);\n```\n\nUnless the referenced request is in status `accepted`, a 404 error will be returned.\n\n##### Example\n\n```javascript\nuber.requests.getMapByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315')\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Get request receipt by request_id](https://developer.uber.com/docs/v1-requests-receipt)\n\n> **Note**: This endpoint requires OAuth authentication with the scope `request_receipt`\n\n```javascript\nuber.requests.getReceiptByIDAsync(request_id);\n```\n\nThe referenced request must be in status `completed`.\n\n##### Example\n\n```javascript\nuber.requests.getReceiptByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315')\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n### /places\n\nThe places endpoint can be accessed ONLY with an OAuth `access_token` authorized with the `places` scope.\n\n> **Note**: As of right now, only two place_ids are allowed: `home` and `work`.\n\n#### [Get home address](https://developer.uber.com/docs/v1-places-get)\n\n```javascript\nuber.places.getHomeAsync();\n```\n\n##### Example\n\n```javascript\nuber.places.getHomeAsync()\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Get work address](https://developer.uber.com/docs/v1-places-get)\n\n```javascript\nuber.places.getWorkAsync();\n```\n\n##### Example\n\n```javascript\nuber.places.getWorkAsync()\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Update home address](https://developer.uber.com/docs/v1-places-put)\n\n```javascript\nuber.places.updateHomeAsync(address);\n```\n\n##### Example\n\n```javascript\nuber.places.updateHomeAsync('685 Market St, San Francisco, CA 94103, USA')\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Update work address](https://developer.uber.com/docs/v1-places-put)\n\n```javascript\nuber.places.updateWorkAsync(address);\n```\n\n##### Example\n\n```javascript\nuber.places.updateWorkAsync('1455 Market St, San Francisco, CA 94103, USA')\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n### /payment-methods\n\nThe payment-methods endpoint can be accessed ONLY with an OAuth `access_token` authorized with the `request` scope.\n\n#### [Get available payment methods](https://developer.uber.com/docs/v1-payment-methods)\n\n```javascript\nuber.payment.getMethodsAsync();\n```\n\n##### Example\n\n```javascript\nuber.payment.getMethodsAsync()\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n### /partners\n\nThe partners endpoints (Driver API) can be accessed ONLY with an OAuth `access_token` authorized with [the respective scopes](https://developer.uber.com/docs/drivers/guides/scopes) (`partner.accounts`, `partner.trips`, or `partner.payments`).\n\n#### [Get driver profile](https://developer.uber.com/docs/drivers/references/api/v1/partners-me-get)\n\n```javascript\nuber.partnerprofile.getProfileAsync();\n```\n\n##### Example\n\n```javascript\nuber.partnerprofile.getProfileAsync()\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Get driver payments](https://developer.uber.com/docs/drivers/references/api/v1/partners-payments-get)\n\n```javascript\nuber.partnerpayments.getPaymentsAsync(offset, limit, from_time, to_time);\n```\n\n##### Parameter\n\n- offset for payments list (sorted by creation time). Defaults to `0`\n- limit of payments list. Defaults to `5`\n- minimum Unix timestamp for filtered payments list\n- maximum Unix timestamp for filtered payments list\n\n##### Example\n\n```javascript\nuber.partnerpayments.getPaymentsAsync(0, 50, 1451606400, 1505160819)\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n#### [Get driver trips](https://developer.uber.com/docs/drivers/references/api/v1/partners-trips-get)\n\n```javascript\nuber.partnertrips.getTripsAsync(offset, limit, from_time, to_time);\n```\n\n##### Parameter\n\n- offset for trips list (sorted by creation time). Defaults to `0`\n- limit of trips list. Defaults to `5`\n- minimum Unix timestamp for filtered trips list\n- maximum Unix timestamp for filtered trips list\n\n##### Example\n\n```javascript\nuber.partnertrips.getTripsAsync(0, 50, 1451606400, 1505160819)\n.then(function(res) { console.log(res); })\n.error(function(err) { console.error(err); });\n```\n\n## Test\n\nYou can execute all existing tests using script `test/allTests.js`. These tests include linting, code coverage, and unit tests.\n\n```sh\nnpm test\n```\n\nIn case you would like to contribute to this project, please ensure that all the tests pass before you create a PR. We have strict code style and code coverage (>= 95%) requirements.\n\n## Version History\n\nThe change-log can be found in the [Wiki: Version History](https://github.com/shernshiou/node-uber/wiki/Version-History).\n"
  },
  {
    "path": "examples/auth-get-products-async.js",
    "content": "var Uber = require('node-uber');\n\n// create new Uber instance\nvar uber = new Uber({\n    client_id: 'YOUR CLIENT ID',\n    client_secret: 'YOUR CLIENT SECRET',\n    server_token: 'YOUR SERVER TOKEN',\n    redirect_uri: 'http://localhost/callback',\n    name: 'nodejs uber wrapper',\n    language: 'en_US',\n    sandbox: true\n});\n\n// get authorization URL\nvar authURL = uber.getAuthorizeUrl(['history', 'profile', 'request', 'places']);\n\n// redirect user to the authURL\n\n// the authorizarion_code will be provided via the callback after logging in using the authURL\nuber.authorizationAsync({\n        authorization_code: 'YOUR AUTH CODE'\n    })\n    .spread(function(access_token, refresh_token, authorizedScopes, tokenExpiration) {\n        // store the user id and associated access_token, refresh_token, scopes and token expiration date\n        console.log('New access_token retrieved: ' + access_token);\n        console.log('... token allows access to scopes: ' + authorizedScopes);\n        console.log('... token is valid until: ' + tokenExpiration);\n        console.log('... after token expiration, re-authorize using refresh_token: ' + refresh_token);\n\n        // chain the promise to retrive all products for location\n        return uber.products.getAllForLocationAsync(3.1357169, 101.6881501);\n    })\n    .then(function(res) {\n        // response with all products\n        console.log(res);\n    })\n    .error(function(err) {\n        console.error(err);\n    });\n"
  },
  {
    "path": "examples/auth-get-products.js",
    "content": "var Uber = require('node-uber');\n\n// create new Uber instance\nvar uber = new Uber({\n    client_id: 'YOUR CLIENT ID',\n    client_secret: 'YOUR CLIENT SECRET',\n    server_token: 'YOUR SERVER TOKEN',\n    redirect_uri: 'http://localhost/callback',\n    name: 'nodejs uber wrapper',\n    language: 'en_US',\n    sandbox: true\n});\n\n// get authorization URL\nvar authURL = uber.getAuthorizeUrl(['history', 'profile', 'request', 'places']);\n\n// redirect user to the authURL\n\n// the authorizarion_code will be provided via the callback after logging in using the authURL\nuber.authorization({\n    authorization_code: 'YOUR AUTH CODE'\n}, function(err, res) {\n    if (err) {\n        console.error(err);\n    } else {\n        // store the user id and associated properties:\n        // access_token = res[0], refresh_token = res[1], scopes = res[2]),and token expiration date = res[3]\n        console.log('New access_token retrieved: ' + res[0]);\n        console.log('... token allows access to scopes: ' + res[2]);\n        console.log('... token is valid until: ' + res[3]);\n        console.log('... after token expiration, re-authorize using refresh_token: ' + res[1]);\n\n        uber.products.getAllForLocation(3.1357169, 101.6881501, function(err, res) {\n            if (err) console.error(err);\n            else console.log(res);\n        });\n    }\n});\n"
  },
  {
    "path": "gulpfile.js",
    "content": "var gulp = require('gulp'),\n    mocha = require('gulp-mocha'),\n    istanbul = require('gulp-istanbul'),\n    eslint = require('gulp-eslint');\n\ngulp.task('lint', function() {\n    // ESLint ignores files with \"node_modules\" paths.\n    // So, it's best to have gulp ignore the directory as well.\n    // Also, Be sure to return the stream from the task;\n    // Otherwise, the task may end before the stream has finished.\n    return gulp.src(['**/*.js', '!node_modules/**', '!coverage/**'])\n        // eslint() attaches the lint output to the \"eslint\" property\n        // of the file object so it can be used by other modules.\n        .pipe(eslint())\n        // eslint.format() outputs the lint results to the console.\n        // Alternatively use eslint.formatEach() (see Docs).\n        .pipe(eslint.format())\n        // To have the process exit with an error code (1) on\n        // lint error, return the stream and pipe to failAfterError last.\n        .pipe(eslint.failAfterError());\n});\n\ngulp.task('pre-test', function() {\n    return gulp.src(['lib/**/*.js'])\n        // Covering files\n        .pipe(istanbul({\n            includeUntested: true\n        }))\n        // Force `require` to return covered files\n        .pipe(istanbul.hookRequire());\n});\n\ngulp.task('test', ['pre-test'], function() {\n    return gulp.src(['test/**/*.js'])\n        .pipe(mocha({\n            reporter: 'spec',\n            //useColors: false,\n            timeout: 5000\n        }))\n        // Creating the reports after tests ran\n        .pipe(istanbul.writeReports())\n        // Enforce a coverage of at least 95%\n        .pipe(istanbul.enforceThresholds({\n            thresholds: {\n                global: 95\n            }\n        }));\n});\n\ngulp.task('default', ['lint', 'pre-test', 'test']);\n"
  },
  {
    "path": "index.js",
    "content": "module.exports = require('./lib/Uber');\n"
  },
  {
    "path": "lib/Uber.js",
    "content": "var request = require('request');\nvar qs = require('querystring');\nvar OAuth = require('oauth');\nvar util = require('util');\nvar Promise = require('bluebird');\nvar NodeGeocoder = require('node-geocoder');\nvar ProxyAgent = require('proxy-agent');\n\nvar resources = {\n  Estimates: require('./resources/riders/Estimates'),\n  Products: require('./resources/riders/Products'),\n  User: require('./resources/riders/User'),\n  Requests: require('./resources/riders/Requests'),\n  Places: require('./resources/riders/Places'),\n  Payment: require('./resources/riders/Payment'),\n  PartnerPayments: require('./resources/drivers/PartnerPayments'),\n  PartnerProfile: require('./resources/drivers/PartnerProfile'),\n  PartnerTrips: require('./resources/drivers/PartnerTrips')\n};\n\nfunction Uber(options) {\n  this.sandbox = options.sandbox\n    ? options.sandbox\n    : false;\n  this.defaults = {\n    client_id: options.client_id,\n    client_secret: options.client_secret,\n    server_token: options.server_token,\n    redirect_uri: options.redirect_uri,\n    name: options.name,\n    base_url: this.sandbox\n      ? 'https://sandbox-api.uber.com/'\n      : 'https://api.uber.com/',\n    base_version: 'v1.2',\n    language: options.language\n      ? options.language\n      : 'en_US',\n    authorize_url: 'https://login.uber.com/oauth/v2/authorize',\n    access_token_url: 'https://login.uber.com/oauth/v2/token',\n    revoke_token_url: 'https://login.uber.com/oauth/v2/revoke',\n    proxy: options.proxy\n      ? options.proxy\n      : ''\n  };\n\n  this.oauth2 = new OAuth.OAuth2(this.defaults.client_id, this.defaults.client_secret, '', this.defaults.authorize_url, this.defaults.access_token_url);\n\n  this.geocoder = NodeGeocoder({\n    provider: \"google\",\n    apiKey: options.google_maps_api_key\n  });\n\n  if (this.defaults.proxy) {\n    this.oauth2.setAgent(new ProxyAgent(this.defaults.proxy));\n  }\n  this.oauth2.useAuthorizationHeaderforGET(true);\n\n  this.resources = resources;\n  this.access_token = options.access_token;\n  this.refresh_token = options.refresh_token;\n  this.tokenExpiration = '';\n  this.authorizedScopes = '';\n\n  this._initResources();\n}\n\nmodule.exports = Uber;\n\nUber.prototype._initResources = function _initResources() {\n  for (var name in this.resources) {\n    if ({}.hasOwnProperty.call(this.resources, name)) {\n      this[name.toLowerCase()] = Promise.promisifyAll(new resources[name](this));\n    }\n  }\n};\n\nUber.prototype.getCoordinatesForAddress = function getCoordinatesForAddress(address, callback) {\n  this.geocoder.geocode(address, function (err, data) {\n    if (err || data.length === 0) {\n      return callback((err\n        ? err\n        : new Error('No coordinates found for: \"' + address + '\"')), {\n          lat: '',\n          lng: ''\n        });\n    }\n\n    const result = { lat: data[0].latitude, lng: data[0].longitude };\n    callback(null, result);\n  });\n};\n\nUber.prototype.replaceAddressWithCoordinates = function\n  replaceAddressWithCoordinates(params, addressField, latField, lngField, callback) {\n  if (this.hasOwnNestedProperty(params, addressField) && !this.getNestedProperty(params, latField) && !this.getNestedProperty(params, lngField)) {\n    // get coordinates from address\n    this.getCoordinatesForAddress(this.getNestedProperty(params, addressField), function (err, data) {\n      if (err) {\n        return callback(err);\n      }\n\n      console.log(data)\n      this.removeNestedProperty(params, addressField);\n      this.setNestedProperty(params, latField, data.lat);\n      this.setNestedProperty(params, lngField, data.lng);\n\n      return callback(null, params);\n    }.bind(this));\n  } else {\n    return callback(null, params);\n  }\n};\n\nUber.prototype.getAuthorizeUrl = function getAuthorizeUrl(scope) {\n  if (!Array.isArray(scope)) {\n    return new Error('Scope is not an array');\n  }\n  if (scope.length === 0) {\n    return new Error('Scope is empty');\n  }\n\n  return this.oauth2.getAuthorizeUrl({ response_type: 'code', redirect_uri: this.defaults.redirect_uri, scope: scope.join(' ') });\n};\n\nUber.prototype.authorization = function authorization(options, callback) {\n  var self = this;\n  var grantType = '';\n  var code = '';\n  var nD = null;\n\n  if (options.hasOwnProperty('authorization_code')) {\n    grantType = 'authorization_code';\n    code = options.authorization_code;\n  } else if (options.hasOwnProperty('refresh_token')) {\n    grantType = 'refresh_token';\n    code = options.refresh_token;\n  } else {\n    return callback(new Error('No authorization_code or refresh_token'));\n  }\n\n  this.oauth2.getOAuthAccessToken(code, {\n    client_id: this.defaults.client_id,\n    client_secret: this.defaults.client_secret,\n    redirect_uri: this.defaults.redirect_uri,\n    grant_type: grantType\n  }, function (err, access_token, refresh_token, results) {\n    if (err) {\n      return callback(err);\n    } else {\n      self.access_token = access_token;\n      self.refresh_token = refresh_token;\n      // store auth scopes\n      self.authorizedScopes = results.scope;\n      // store expiration date\n      nD = new Date();\n      // expires value indicates seconds\n      nD.setSeconds(nD.getSeconds() + results.expires_in);\n      self.tokenExpiration = nD;\n      return callback(null, [self.access_token, self.refresh_token, self.authorizedScopes, self.tokenExpiration]);\n    }\n  });\n\n  return self;\n};\n\nUber.prototype.authorizationAsync = Promise.promisify(Uber.prototype.authorization);\n\nUber.prototype.delete = function (options, callback) {\n  return this.modifierMethodHelper(options, callback, 'delete');\n};\n\nUber.prototype.patch = function patch(options, callback) {\n  return this.modifierMethodHelper(options, callback, 'patch');\n};\n\nUber.prototype.post = function post(options, callback) {\n  return this.modifierMethodHelper(options, callback, 'post');\n};\n\nUber.prototype.put = function put(options, callback) {\n  return this.modifierMethodHelper(options, callback, 'put');\n};\n\nUber.prototype.modifierMethodExecute = function modifierMethodExecute(method, params, callback) {\n  if (this.defaults.proxy) {\n    params.agent = new ProxyAgent(this.defaults.proxy);\n  }\n\n  switch (method) {\n    case 'delete':\n      request.delete(params, callback);\n      break;\n    case 'post':\n      request.post(params, callback);\n      break;\n    case 'put':\n      request.put(params, callback);\n      break;\n    case 'patch':\n      request.patch(params, callback);\n      break;\n  }\n};\n\nUber.prototype.modifierMethodHelper = function modifierMethodHelper(options, callback, method) {\n  var access_type;\n  var self = this;\n  var localCallback = function localCallback(err, data, res) {\n    // shared callback between put, post, patch, and delete requests\n    if (err || data.statusCode >= 400) {\n      return callback(((err)\n        ? err\n        : 'HTTP Response with error code: ' + data.statusCode), data);\n    } else {\n      return callback(null, res);\n    }\n  };\n  var refreshCallback = function refreshCallback() {\n    if (!self.checkScopes(options)) {\n      return callback(new Error('Required scope not found'));\n    }\n\n    // remove scope parameter from options\n    delete options.scope;\n\n    var params = {\n      url: self.getRequestURL(options.version, options.url),\n      json: true,\n      headers: {\n        'Content-Type': 'application/json',\n        'Authorization': access_type,\n        'Accept-Language': self.defaults.language\n      },\n      body: ((options.params)\n        ? options.params\n        : '')\n    };\n\n    self.modifierMethodExecute(method, params, localCallback);\n\n    return self;\n  };\n  if (options && options.server_token) {\n    access_type = 'Token ' + this.defaults.server_token;\n    refreshCallback();\n  } else {\n    if (!this.access_token) {\n      return callback(new Error('Invalid access token'));\n    } else {\n      // defaults to OAuth with access_token\n      // auto renew if required\n      if (this.isTokenStale()) {\n        this.authorization({\n          refresh_token: this.refresh_token\n        }, function (err, res) {\n          if (err) {\n            return callback(err);\n          } else {\n            access_type = 'Bearer ' + res[0];\n            refreshCallback();\n          }\n        });\n      } else {\n        access_type = 'Bearer ' + this.access_token;\n        refreshCallback();\n      }\n    }\n  }\n};\n\nUber.prototype.createAccessHeader = function createAccessHeader(server_token) {\n  var access_type;\n\n  if (server_token) {\n    access_type = 'Token ' + this.defaults.server_token;\n  } else {\n    if (this.access_token) {\n      access_type = 'Bearer ' + this.access_token;\n    }\n  }\n\n  return access_type;\n};\n\nUber.prototype.get = function get(options, callback) {\n  var access_type = this.createAccessHeader(options.server_token);\n  if (!access_type) {\n    return callback(new Error('Invalid access token'), 'A valid access token is required for this request');\n  }\n  var url = this.getRequestURL(options.version, options.url);\n\n  if (!this.checkScopes(options)) {\n    return callback(new Error('Required scope not found'));\n  }\n\n  // remove scope parameter from options\n  delete options.scope;\n\n  // add all further option params\n  if (options.params) {\n    url += '?' + qs.stringify(options.params);\n  }\n\n  var reqOptions = {\n    url: url,\n    json: true,\n    headers: {\n      'Content-Type': 'application/json',\n      'Authorization': access_type,\n      'Accept-Language': this.defaults.language\n    }\n  };\n  if (this.defaults.proxy) {\n    reqOptions.agent = new ProxyAgent(this.defaults.proxy);\n  }\n\n  request.get(reqOptions, function (err, data, res) {\n    if (err || data.statusCode >= 400) {\n      return callback((err\n        ? err\n        : data), res);\n    } else {\n      return callback(null, res);\n    }\n  });\n\n  return this;\n};\n\nUber.prototype.checkScopes = function checkScopes(options) {\n  if (!options || !options.scope) {\n    // checking scopes is not relevant\n    return true;\n  }\n\n  // check if options.scope is array\n  if (options.scope && Array === options.scope.constructor) {\n    var regExp;\n    for (var i = 0; i < options.scope.length; i++) {\n      // regEx is required to avoid mismatch between\n      // request and request_receipt\n      regExp = new RegExp('\\\\b' + options.scope[i] + '\\\\b', 'gi');\n      if (regExp.test(this.authorizedScopes)) {\n        return true;\n      }\n    }\n    return false;\n  } else {\n    if (this.authorizedScopes.indexOf(options.scope) > -1) {\n      return true;\n    } else {\n      return false;\n    }\n  }\n};\n\nUber.prototype.revokeToken = function revokeToken(token, callback) {\n  if (typeof token !== \"string\" || token.length === 0) {\n    return callback(new Error('Passed token is not acceptable'));\n  }\n\n  request.post(this.defaults.revoke_token_url, {\n    form: {\n      client_id: this.defaults.client_id,\n      client_secret: this.defaults.client_secret,\n      token: token\n    }\n  }, function (err, res, body) {\n    if (err) {\n      return callback(err);\n    }\n\n    return callback(null, res);\n  });\n};\n\nUber.prototype.revokeTokenAsync = Promise.promisify(Uber.prototype.revokeToken);\n\nUber.prototype.clearTokens = function clearTokens() {\n  this.access_token = null;\n  this.refresh_token = null;\n  this.tokenExpiration = null;\n  this.authorizedScopes = null;\n};\n\nUber.prototype.setTokens = function setTokens(access_token, refresh_token, tokenExpiration, authorizedScopes) {\n  this.access_token = access_token;\n  this.refresh_token = refresh_token;\n  this.tokenExpiration = tokenExpiration;\n  this.authorizedScopes = authorizedScopes;\n}\n\nUber.prototype.isNumeric = function isNumeric(input) {\n  return (!input || isNaN(input))\n    ? false\n    : true;\n};\n\nUber.prototype.hasOwnNestedProperty = function hasOwnNestedProperty(obj, key) {\n  return key.split('.').every(function (x) {\n    if (typeof obj !== 'object' || obj === null || !(x in obj))\n      return false;\n    obj = obj[x];\n    return true;\n  });\n};\n\nUber.prototype.getNestedProperty = function getNestedProperty(obj, key) {\n  return key.split(\".\").reduce(function (o, x) {\n    return (typeof o === 'undefined' || o === null)\n      ? o\n      : o[x];\n  }, obj);\n};\n\nUber.prototype.removeNestedProperty = function removeNestedProperty(obj, key) {\n  var props = key.split('.');\n  var propName = props[props.length - 1];\n  for (var p in obj) {\n    if (obj.hasOwnProperty(p)) {\n      if (p === propName) {\n        delete obj[p];\n      } else if (typeof obj[p] === 'object') {\n        this.removeNestedProperty(obj[p], propName);\n      }\n    }\n  }\n  return obj;\n};\n\nUber.prototype.setNestedProperty = function setNestedProperty(obj, key, value) {\n  var schema = obj;\n  var pList = key.split('.');\n  var len = pList.length;\n  for (var i = 0; i < len - 1; i++) {\n    var elem = pList[i];\n    schema = schema[elem];\n  }\n\n  schema[pList[len - 1]] = value;\n};\n\nUber.prototype.getRequestURL = function getRequestURL(version, url) {\n  return this.defaults.base_url + (version\n    ? version\n    : this.defaults.base_version) + '/' + url;\n};\n\nUber.prototype.isTokenStale = function isTokenStale() {\n  var nD = new Date();\n  var threshold = 500;\n  nD.setSeconds(nD.getSeconds() + threshold);\n  return nD > this.tokenExpiration;\n};\n\nUber.prototype.isSurge = function isSurge(err) {\n  return err.hasOwnProperty('surge_confirmation');\n};\n"
  },
  {
    "path": "lib/resources/drivers/PartnerPayments.js",
    "content": "function PartnerPayments(uber) {\n  this._uber = uber;\n  this.path = 'partners/payments';\n  this.requiredScope = 'partner.payments';\n}\n\nmodule.exports = PartnerPayments;\n\nPartnerPayments.prototype.getPayments = function getPayments(off, lim, from, to, callback) {\n  var newOffset = off || 0;\n  // ensure query limit is set. Maximum is 50. Default is 5.\n  var newLimit = (lim)\n    ? Math.min(lim, 50)\n    : 5;\n\n  var params = {\n    offset: newOffset,\n    limit: newLimit\n  };\n\n  if (parseInt(from, 10) > 0) {\n    params['from_time'] = from;\n  }\n\n  if (parseInt(to, 10) > 0) {\n    params['to_time'] = to;\n  }\n\n  return this._uber.get({\n    url: this.path,\n    version: 'v1',\n    params: params,\n    scope: this.requiredScope\n  }, callback);\n};\n"
  },
  {
    "path": "lib/resources/drivers/PartnerProfile.js",
    "content": "function PartnerProfile(uber) {\n  this._uber = uber;\n  this.path = 'partners/me';\n  this.requiredScope = 'partner.accounts';\n}\n\nmodule.exports = PartnerProfile;\n\nPartnerProfile.prototype.getProfile = function getProfile(callback) {\n  return this._uber.get({\n    url: this.path,\n    version: 'v1',\n    scope: this.requiredScope\n  }, callback);\n};\n"
  },
  {
    "path": "lib/resources/drivers/PartnerTrips.js",
    "content": "function PartnerTrips(uber) {\n  this._uber = uber;\n  this.path = 'partners/trips';\n  this.requiredScope = 'partner.trips';\n}\n\nmodule.exports = PartnerTrips;\n\nPartnerTrips.prototype.getTrips = function getTrips(off, lim, from, to, callback) {\n  var newOffset = off || 0;\n  // ensure query limit is set. Maximum is 50. Default is 5.\n  var newLimit = (lim)\n    ? Math.min(lim, 50)\n    : 5;\n\n  var params = {\n    offset: newOffset,\n    limit: newLimit\n  };\n\n  if (parseInt(from, 10) > 0) {\n    params['from_time'] = from;\n  }\n\n  if (parseInt(to, 10) > 0) {\n    params['to_time'] = to;\n  }\n\n  return this._uber.get({\n    url: this.path,\n    version: 'v1',\n    params: params,\n    scope: this.requiredScope\n  }, callback);\n};\n"
  },
  {
    "path": "lib/resources/riders/Estimates.js",
    "content": "function Estimates(uber) {\n    this._uber = uber;\n    this.path = 'estimates';\n}\n\nmodule.exports = Estimates;\n\nEstimates.prototype.getPriceForRouteByAddress = function getPriceForRouteByAddress(startAddress, endAddress, seats, callback) {\n    this._uber.getCoordinatesForAddress(startAddress, function(err, startData) {\n        if(err) {\n            // check first if seats (optional) is provided\n            return (typeof seats === 'function' ? seats(err) : callback(err));\n        }\n\n        this._uber.getCoordinatesForAddress(endAddress, function(err2, endData) {\n            if(err2) {\n                return (typeof seats === 'function' ? seats(err2) : callback(err2));\n            }\n\n            return this.getPriceForRoute(\n                startData.lat,\n                startData.lng,\n                endData.lat,\n                endData.lng,\n                seats,\n                callback\n            );\n        }.bind(this));\n    }.bind(this));\n};\n\nEstimates.prototype.getPriceForRoute = function getPriceForRoute(startLat,\n    startLon, endLat, endLon, seats, callback) {\n    // seats is optional\n    if (typeof seats === 'function') {\n        callback = seats;\n        // set to the default of 2 seats\n        seats = 2;\n    }\n\n    if (!startLat || !startLon) {\n        return callback(new Error('Invalid starting point latitude & longitude'));\n    }\n\n    if (!endLat || !endLon) {\n        return callback(new Error('Invalid ending point latitude & longitude'));\n    }\n\n    if (!this._uber.isNumeric(seats)) {\n        seats = 2;\n    }\n\n    return this._uber.get({\n        url: this.path + '/price',\n        params: {\n            start_latitude: startLat,\n            start_longitude: startLon,\n            end_latitude: endLat,\n            end_longitude: endLon,\n            seat_count: seats\n        },\n        server_token: true\n    }, callback);\n};\n\nEstimates.prototype.getETAForAddress = function getETAForAddress(address, id, callback) {\n    this._uber.getCoordinatesForAddress(address, function(err, data) {\n        if(err) {\n            // check first if ID (optional) is provided\n            return (typeof id === 'function' ? id(err) : callback(err));\n        }\n\n        return this.getETAForLocation(\n            data.lat,\n            data.lng,\n            id,\n            callback\n        );\n    }.bind(this));\n};\n\nEstimates.prototype.getETAForLocation = function getETAForLocation(lat, lon, id, callback) {\n    if (typeof id === 'function') {\n        callback = id;\n        id = undefined;\n    }\n\n    if (!lat || !lon) {\n        return callback(new Error('Invalid latitude & longitude'));\n    }\n\n    // add optional product_id in case it's set\n    var par = (id && id !== '') ? {\n        start_latitude: lat,\n        start_longitude: lon,\n        product_id: id\n    } : {\n        start_latitude: lat,\n        start_longitude: lon\n    };\n\n    return this._uber.get({\n        url: this.path + '/time',\n        params: par,\n        server_token: true\n    }, callback);\n};\n"
  },
  {
    "path": "lib/resources/riders/Payment.js",
    "content": "function Payment(uber) {\n    this._uber = uber;\n    this.path = 'payment-methods';\n    this.requiredScope = 'request';\n}\n\nmodule.exports = Payment;\n\nPayment.prototype.getMethods = function getMethods(callback) {\n    return this._uber.get({\n        url: this.path,\n        scope: this.requiredScope\n    }, callback);\n};\n"
  },
  {
    "path": "lib/resources/riders/Places.js",
    "content": "function Places(uber) {\n  this._uber = uber;\n  this.path = 'places';\n  this.requiredScope = 'places';\n}\n\nmodule.exports = Places;\n\nPlaces.prototype.getByID = function getByID(id, callback) {\n  if (!id) {\n    return callback(new Error('Invalid place_id'));\n  }\n\n  // as long as only two ids are allowed\n  if (id !== 'home' && id !== 'work') {\n    return callback(new Error('place_id needs to be either \"home\" or \"work\"'));\n  }\n\n  var options = {\n    url: this.path + '/' + id,\n    scope: this.requiredScope\n  };\n\n  return this._uber.get(options, callback);\n};\n\nPlaces.prototype.getHome = function getHome(callback) {\n  return this.getByID('home', callback);\n};\n\nPlaces.prototype.getWork = function getWork(callback) {\n  return this.getByID('work', callback);\n};\n\nPlaces.prototype.updateByID = function updateByID(id, newAddress, callback) {\n  if (!id) {\n    return callback(new Error('Invalid place_id'));\n  }\n\n  // as long as only two ids are allowed\n  if (id !== 'home' && id !== 'work') {\n    return callback(new Error('place_id needs to be either \"home\" or \"work\"'));\n  }\n\n  if (!newAddress) {\n    return callback(new Error('Invalid address'));\n  }\n\n  return this._uber.put({\n    url: this.path + '/' + id,\n    params: { address: newAddress },\n    scope: this.requiredScope\n  }, callback);\n};\n\nPlaces.prototype.updateHome = function updateHome(newAddress, callback) {\n  return this.updateByID('home', newAddress, callback);\n};\n\nPlaces.prototype.updateWork = function updateWork(newAddress, callback) {\n  return this.updateByID('work', newAddress, callback);\n};\n"
  },
  {
    "path": "lib/resources/riders/Products.js",
    "content": "function Products(uber) {\n    this._uber = uber;\n    this.path = 'products';\n}\n\nmodule.exports = Products;\n\nProducts.prototype.getAllForAddress = function getAllForAddress(address, callback) {\n    this._uber.getCoordinatesForAddress(address, function(err, data) {\n        if(err) {\n            return callback(err);\n        }\n\n        return this.getAllForLocation(\n            data.lat,\n            data.lng,\n            callback\n        );\n    }.bind(this));\n};\n\nProducts.prototype.getAllForLocation = function getAllForLocation(lat, lon, callback) {\n    if (!lat || !lon) {\n        return callback(new Error('Invalid latitude & longitude'));\n    }\n\n    return this._uber.get({\n        url: this.path,\n        params: {\n            latitude: lat,\n            longitude: lon\n        },\n        server_token: true\n    }, callback);\n};\n\nProducts.prototype.getByID = function getByID(id, callback) {\n    if (!id) {\n        return callback(new Error('Missing product_id parameter'));\n    }\n\n    return this._uber.get({\n        url: this.path + '/' + id,\n        server_token: true\n    }, callback);\n};\n\nProducts.prototype.setSurgeMultiplierByID = function setSurgeMultiplierByID(id, multiplier, callback) {\n    if (!id) {\n        return callback(new Error('Invalid product_id'));\n    }\n\n    if (this._uber.sandbox) {\n        if (!this._uber.isNumeric(multiplier)) {\n            return callback(new Error('Invalid surge multiplier'));\n        } else {\n            return this._uber.put({\n                // this is required only for the PUT method\n                url: 'sandbox/' + this.path + '/' + id,\n                params: {\n                    surge_multiplier: parseFloat(multiplier)\n                },\n                server_token: true\n            }, callback);\n        }\n    } else {\n        return callback(new Error('Setting surge multiplier is only allowed in Sandbox mode'));\n    }\n};\n\nProducts.prototype.setDriversAvailabilityByID = function setDriversAvailabilityByID(id, availability, callback) {\n    if (!id) {\n        return callback(new Error('Invalid product_id'));\n    }\n\n    if (this._uber.sandbox) {\n        if (typeof availability !== 'boolean') {\n            return callback(new Error('Availability needs to be a boolean'));\n        } else {\n            return this._uber.put({\n                // this is required only for the PUT method\n                url: 'sandbox/' + this.path + '/' + id,\n                params: {\n                    drivers_available: availability\n                },\n                server_token: true\n            }, callback);\n        }\n    } else {\n        return callback(new Error('Setting driver`s availability is only allowed in Sandbox mode'));\n    }\n};\n"
  },
  {
    "path": "lib/resources/riders/Requests.js",
    "content": "function Requests(uber) {\n    this._uber = uber;\n    this.path = 'requests';\n    this.requiredScope = ['request', 'all_trips', 'request_receipt'];\n}\n\nmodule.exports = Requests;\n\nRequests.prototype.create = function create(parameters, callback) {\n    var self = this;\n    if (!parameters) {\n        return callback(new Error('Invalid parameters'));\n    }\n    function localCallback(err, res) {\n        if (!err) {\n            return callback(err, res);\n        } else if (!res) {\n            return callback(err, res);\n        }\n        else if (res.statusCode === 409 && res.body.hasOwnProperty('meta')) {\n            var meta = res.body.meta;\n            if (meta.hasOwnProperty('surge_confirmation')) {\n                var serr = {};\n                serr.message = err;\n                serr.surge_confirmation = meta.surge_confirmation;\n                parameters.surge_confirmation_id = meta.surge_confirmation.surge_confirmation_id;\n                self._uber.currentRequestParameters = parameters;\n                return callback(serr, res);\n            } else {\n                return callback(err, res);\n            }\n        }\n    }\n    // replace addresses with node-geocoder coordinates if provided\n    this._uber\n        .replaceAddressWithCoordinates(\n            parameters,\n            'startAddress',\n            'start_latitude',\n            'start_longitude',\n            function(startErr, startData) {\n                if (startErr) {\n                    return callback(startErr);\n                }\n\n                this._uber\n                    .replaceAddressWithCoordinates(\n                        startData,\n                        'endAddress',\n                        'end_latitude',\n                        'end_longitude',\n                        function(endErr, endData) {\n                            if (endErr) {\n                                return callback(endErr);\n                            }\n                            return this._uber.post({\n                                url: this.path,\n                                params: endData,\n                                scope: this.requiredScope[0]\n                            }, localCallback);\n                        }.bind(this)\n                    );\n            }.bind(this)\n        );\n};\n\nRequests.prototype.acceptSurgeForLastRequest = function acceptSurgeForLastRequest(callback) {\n  if (! this._uber.hasOwnProperty('currentRequestParameters')) {\n      return callback('No active request found for this session', null);\n  } else {\n      var params = JSON.parse(JSON.stringify(this._uber.currentRequestParameters));\n      // invalidate session\n      delete this._uber.currentRequestParameters;\n      return this._uber.post({\n          url: this.path,\n          params: params,\n          scope: this.requiredScope[0]\n      }, callback);\n  }\n};\n\nRequests.prototype.getCurrent = function getCurrent(callback) {\n    return this.getByID('current', callback);\n};\n\nRequests.prototype.getByID = function getByID(id, callback) {\n    if (!id) {\n        return callback(new Error('Invalid request_id'));\n    }\n\n    return this._uber.get({\n        url: this.path + '/' + id,\n        scope: [this.requiredScope[0], this.requiredScope[1]]\n    }, callback);\n};\n\nRequests.prototype.getMapByID = function getMapByID(id, callback) {\n    if (!id) {\n        return callback(new Error('Invalid request_id'));\n    }\n\n    return this._uber.get({\n        url: this.path + '/' + id + '/map',\n        scope: this.requiredScope[0]\n    }, callback);\n};\n\nRequests.prototype.getReceiptByID = function getReceiptByID(id, callback) {\n    if (!id) {\n        return callback(new Error('Invalid request_id'));\n    }\n\n    return this._uber.get({\n        url: this.path + '/' + id + '/receipt',\n        scope: this.requiredScope[2]\n    }, callback);\n};\n\nRequests.prototype.updateCurrent = function updateCurrent(parameters, callback) {\n    if (!parameters) {\n        return callback(new Error('Invalid parameters'));\n    }\n\n    return this.updateByID('current', parameters, callback);\n};\n\nRequests.prototype.updateByID = function updateByID(id, parameters, callback) {\n    if (!id) {\n        return callback(new Error('Invalid request_id'));\n    }\n\n    if (!parameters) {\n        return callback(new Error('Invalid parameters'));\n    }\n\n    // replace addresses with node-geocoder coordinates if provided\n    this._uber\n        .replaceAddressWithCoordinates(\n            parameters,\n            'startAddress',\n            'start_latitude',\n            'start_longitude',\n            function(startErr, startData) {\n                if (startErr) {\n                    return callback(startErr);\n                }\n\n                this._uber\n                    .replaceAddressWithCoordinates(\n                        startData,\n                        'endAddress',\n                        'end_latitude',\n                        'end_longitude',\n                        function(endErr, endData) {\n                            if (endErr) {\n                                return callback(endErr);\n                            }\n\n                            return this._uber.patch({\n                                url: this.path + '/' + id,\n                                params: endData,\n                                scope: this.requiredScope[0]\n                            }, callback);\n                        }.bind(this)\n                    );\n            }.bind(this)\n        );\n};\n\nRequests.prototype.setStatusByID = function setStatusByID(id, newSatus, callback) {\n    if (!this._uber.sandbox) {\n        return callback(new Error('PUT method for requests is only allowed in Sandbox mode'));\n    }\n\n    if (!id) {\n        return callback(new Error('Invalid request_id'));\n    }\n\n    if (!newSatus) {\n        return callback(new Error('Invalid status'));\n    }\n\n    return this._uber.put({\n            // this is required only for the PUT method\n            url: 'sandbox/' + this.path + '/' + id,\n            params: {\n                status: newSatus\n            },\n            scope: this.requiredScope[0]\n        },\n        callback);\n};\n\nRequests.prototype.deleteCurrent = function deleteCurrent(callback) {\n    return this.deleteByID('current', callback);\n};\n\nRequests.prototype.deleteByID = function deleteByID(id, callback) {\n    if (!id) {\n        return callback(new Error('Invalid request_id'));\n    }\n\n    return this._uber.delete({\n        url: this.path + '/' + id,\n        scope: this.requiredScope[0]\n    }, callback);\n};\n\nRequests.prototype.getEstimates = function getEstimates(parameters, callback) {\n    if (!parameters) {\n        return callback(new Error('Invalid parameters'));\n    }\n\n    // replace addresses with node-geocoder coordinates if provided\n    this._uber\n        .replaceAddressWithCoordinates(\n            parameters,\n            'startAddress',\n            'start_latitude',\n            'start_longitude',\n            function(startErr, startData) {\n                if (startErr) {\n                    return callback(startErr);\n                }\n\n                this._uber\n                    .replaceAddressWithCoordinates(\n                        startData,\n                        'endAddress',\n                        'end_latitude',\n                        'end_longitude',\n                        function(endErr, endData) {\n                            if (endErr) {\n                                return callback(endErr);\n                            }\n\n                            return this._uber.post({\n                                url: this.path + '/estimate',\n                                params: endData,\n                                scope: this.requiredScope[0]\n                            }, callback);\n                        }.bind(this)\n                    );\n            }.bind(this)\n        );\n};\n"
  },
  {
    "path": "lib/resources/riders/User.js",
    "content": "function User(uber) {\n  this._uber = uber;\n  this.path = ['me', 'history'];\n  this.requiredScope = ['profile', 'history', 'history_lite'];\n}\n\nmodule.exports = User;\n\nUser.prototype.getHistory = function getHistory(off, lim, callback) {\n  var newOffset = off || 0;\n  // ensure query limit is set. Maximum is 50. Default is 5.\n  var newLimit = (lim) ? Math.min(lim, 50) : 5;\n\n  return this._uber.get({\n    url: this.path[1],\n    params: { offset: newOffset, limit: newLimit },\n    scope: [this.requiredScope[1], this.requiredScope[2]]\n  }, callback);\n};\n\nUser.prototype.getProfile = function getProfile(callback) {\n  return this._uber.get({\n    url: this.path[0],\n    scope: this.requiredScope[0]\n  }, callback);\n};\n\nUser.prototype.applyPromo = function applyPromo(promo, callback) {\n  return this._uber.patch({\n    url: this.path[0],\n    params: { applied_promotion_codes: promo },\n    scope: this.requiredScope[0]\n  }, callback);\n}\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"node-uber\",\n  \"version\": \"2.0.0\",\n  \"description\": \"A Node.js wrapper for Uber API\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"test\": \"gulp\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/shernshiou/node-uber.git\"\n  },\n  \"author\": {\n    \"name\": \"Shern Shiou Tan\",\n    \"email\": \"shernshiou@gmail.com\",\n    \"url\": \"http://blog.shernshiou.com\"\n  },\n  \"contributors\": [\n    {\n      \"name\": \"Alexander Graebe\",\n      \"email\": \"alex.graebe@gmail.com\",\n      \"url\": \"https://twitter.com/agraebe\"\n    }\n  ],\n  \"license\": \"MIT\",\n  \"dependencies\": {\n    \"bluebird\": \"^3.4.7\",\n    \"node-geocoder\": \"^3.22.0\",\n    \"oauth\": \"^0.9.15\",\n    \"proxy-agent\": \"^2.0.0\",\n    \"request\": \"^2.79.0\"\n  },\n  \"devDependencies\": {\n    \"chai\": \"^4.1.2\",\n    \"codeclimate-test-reporter\": \"^0.5.0\",\n    \"gulp\": \"^3.9.1\",\n    \"gulp-eslint\": \"^4.0.0\",\n    \"gulp-istanbul\": \"^1.1.2\",\n    \"gulp-mocha\": \"^3.0.1\",\n    \"gulp-util\": \"^3.0.8\",\n    \"istanbul\": \"^0.4.5\",\n    \"mocha\": \"^3.5.3\",\n    \"nock\": \"^9.0.14\",\n    \"sinon\": \"^3.2.1\",\n    \"sinon-chai\": \"^2.13.0\",\n    \"superagent\": \"^3.6.0\"\n  },\n  \"engines\": {\n    \"node\": \">6.10\",\n    \"npm\": \">3.10.10\"\n  }\n}\n"
  },
  {
    "path": "test/allTests.js",
    "content": "var common = require(\"./common\"),\n    nock = common.nock,\n    jp = common.jsonReplyPath,\n    key = common.key,\n    jr = common.jsonReply,\n    ac = common.authCode,\n    acNP = common.authCodeNoProfile,\n    acNPl = common.authCodeNoPlaces,\n    acNR = common.authCodeNoRequest,\n    acTE = common.authCodeTokenExpired,\n    acTR = common.authCodeTokenRefresh,\n    acTNR = common.authCodeTokenNoRefresh,\n    acRTE = common.authCodeRefreshTokenError,\n    rPC = common.requestProductCreate,\n    rPS = common.requestProductSurge,\n    rSC = common.requestSurgeConfirmationID,\n    rPSOE = common.requestProductSomeOtherError;\nfunction importTest(name, path) {\n    describe(name, function() {\n        before(function() {\n            defineNocks();\n        });\n        require(path);\n    });\n}\n\ndescribe(\"Running all tests ...\", function() {\n    importTest(\"Uber client general tests\", './general');\n    // Auth\n    importTest(\"OAuth2 authorization methods\", './auth/oauth');\n    importTest(\"OAuth2 authorization methods (Async)\", './auth/oauthAsync');\n    // Riders\n    importTest(\"/Estimates\", './riders/estimates');\n    importTest(\"/Estimates (Async)\", './riders/estimatesAsync');\n    importTest(\"/Payment-Methods\", './riders/payment-methods');\n    importTest(\"/Payment-Methods (Async)\", './riders/payment-methodsAsync');\n    importTest(\"/Places\", './riders/places');\n    importTest(\"/Places (Async)\", './riders/placesAsync');\n    importTest(\"/Products\", './riders/products');\n    importTest(\"/Products (Async)\", './riders/productsAsync');\n    importTest(\"/Requests\", './riders/requests');\n    importTest(\"/Requests (Async)\", './riders/requestsAsync');\n    importTest(\"/User\", './riders/user');\n    importTest(\"/User (Async)\", './riders/userAsync');\n    // Drivers\n    importTest(\"/Partners/Me\", './drivers/profile');\n    importTest(\"/Partner/Me (Async)\", './drivers/profileAsync');\n    importTest(\"/Partners/Payments\", './drivers/payments');\n    importTest(\"/Partner/Payments (Async)\", './drivers/paymentsAsync');\n    importTest(\"/Partners/Trips\", './drivers/trips');\n    importTest(\"/Partner/Trips (Async)\", './drivers/tripsAsync');\n});\n\ndefineNocks = function() {\n    // Login\n    nock('https://login.uber.com')\n        .persist()\n        .post('/oauth/v2/revoke')\n        .reply(200)\n        .post('/oauth/v2/token', {\n            code: ''\n        })\n        .reply(500)\n        .post('/oauth/v2/token', {\n            code: ac\n        })\n        .replyWithFile(200, jp('auth/token'))\n        .post('/oauth/v2/token', {\n            refresh_token: ac\n        })\n        .replyWithFile(200, jp('auth/token'))\n        .post('/oauth/v2/token', {\n            code: acNP\n        })\n        .replyWithFile(200, jp('auth/tokenNoProfile'))\n        .post('/oauth/v2/token', {\n            code: acNPl\n        })\n        .replyWithFile(200, jp('auth/tokenNoPlaces'))\n        .post('/oauth/v2/token', {\n            code: acNR\n        })\n        .replyWithFile(200, jp('auth/tokenNoRequest'))\n        .post('/oauth/v2/token', {\n            code: acTE\n        })\n        .replyWithFile(200, jp('auth/tokenExpired'))\n        .post('/oauth/v2/token', {\n            refresh_token: acTR\n        })\n        .replyWithFile(200, jp('auth/tokenRefreshed'))\n        .post('/oauth/v2/token', {\n            code: acTNR\n        })\n        .replyWithFile(200, jp('auth/tokenNoRefresh'))\n        .post('/oauth/v2/token', {\n            refresh_token: acRTE\n        })\n        .reply(500);\n\n    // Endpoints accessible with OAuth2 Token\n    nock('https://api.uber.com', {\n            reqheaders: {\n                'Authorization': 'Bearer ' + jr('auth/token').access_token\n            }\n        })\n        .persist()\n        // Payment-Methods\n        .get('/v1.2/payment-methods')\n        .replyWithFile(200, jp('riders/paymentMethod'))\n        // Places\n        .get('/v1.2/places/home')\n        .replyWithFile(200, jp('riders/placeHome'))\n        .put('/v1.2/places/home')\n        .replyWithFile(200, jp('riders/placeHome'))\n        .get('/v1.2/places/work')\n        .replyWithFile(200, jp('riders/placeWork'))\n        .put('/v1.2/places/work')\n        .replyWithFile(200, jp('riders/placeWork'))\n        .get('/v1.2/places/shop')\n        .reply(404)\n        .put('/v1.2/places/shop')\n        .reply(404)\n        // User\n        .get('/v1.2/me')\n        .replyWithFile(200, jp('riders/profile'))\n        .patch('/v1.2/me', {\n            applied_promotion_codes: 'FREE_RIDEZ'\n        })\n        .replyWithFile(200, jp('riders/profilePromoSuccess'))\n        .patch('/v1.2/me', {\n            applied_promotion_codes: 'already-used-code'\n        })\n        .replyWithFile(400, jp('riders/profilePromoError'))\n        .get(function(uri) {\n            var parts = uri.split('/v1.2/history?offset=0&limit=');\n            if (parts.length !== 2) {\n                return false;\n            }\n            // range should be between 1 and 50\n            return (parts[1] > 0 && parts[1] <= 50);\n        })\n        .replyWithFile(200, jp('riders/history'))\n        // Requests\n        .get('/v1.2/requests/current')\n        .replyWithFile(200, jp('riders/requestAccept'))\n        .post('/v1.2/requests', {\n            product_id : rPC\n        })\n        .replyWithFile(200, jp('riders/requestCreate'))\n        .post('/v1.2/requests', {\n            product_id : rPS,\n            surge_confirmation_id : rSC\n        })\n        .replyWithFile(200, jp('riders/requestCreate'))\n        .post('/v1.2/requests', {\n            product_id : rPS\n        })\n        .replyWithFile(409, jp('riders/requestSurge'))\n        .post('/v1.2/requests', {\n            product_id : rPSOE\n        })\n        .replyWithFile(409, jp('riders/requestFareExpired'))\n        .patch('/v1.2/requests/current')\n        .reply(204)\n        .delete('/v1.2/requests/current')\n        .reply(204)\n        .post('/v1.2/requests/estimate')\n        .replyWithFile(200, jp('riders/requestEstimate'))\n        .get('/v1.2/requests/17cb78a7-b672-4d34-a288-a6c6e44d5315')\n        .replyWithFile(200, jp('riders/requestAccept'))\n        .patch('/v1.2/requests/abcd')\n        .reply(404)\n        .get('/v1.2/requests/abcd')\n        .reply(404)\n        .patch('/v1.2/requests/17cb78a7-b672-4d34-a288-a6c6e44d5315')\n        .reply(204)\n        .delete('/v1.2/requests/17cb78a7-b672-4d34-a288-a6c6e44d5315')\n        .reply(204)\n        .get('/v1.2/requests/17cb78a7-b672-4d34-a288-a6c6e44d5315/map')\n        .replyWithFile(200, jp('riders/requestMap'))\n        .get('/v1.2/requests/17cb78a7-b672-4d34-a288-a6c6e44d5315/receipt')\n        .replyWithFile(200, jp('riders/requestReceipt'))\n        // Driver Partners\n        .get('/v1/partners/me')\n        .replyWithFile(200, jp('drivers/partnerProfile'))\n        .get('/v1/partners/payments?offset=0&limit=5&from_time=1451606400&to_time=1505160819')\n        .replyWithFile(200, jp('drivers/partnerPayments'))\n        .get('/v1/partners/payments?offset=0&limit=50&from_time=1451606400&to_time=1505160819')\n        .replyWithFile(200, jp('drivers/partnerPayments'))\n        .get('/v1/partners/payments?offset=0&limit=5')\n        .replyWithFile(200, jp('drivers/partnerPayments'))\n        .get('/v1/partners/trips?offset=0&limit=5&from_time=1451606400&to_time=1505160819')\n        .replyWithFile(200, jp('drivers/partnerTrips'))\n        .get('/v1/partners/trips?offset=0&limit=50&from_time=1451606400&to_time=1505160819')\n        .replyWithFile(200, jp('drivers/partnerTrips'))\n        .get('/v1/partners/trips?offset=0&limit=5')\n        .replyWithFile(200, jp('drivers/partnerTrips'));\n\n\n    // Endpoints accessible with server_token\n    nock('https://api.uber.com', {\n            reqheaders: {\n                'Authorization': 'Token ' + key.server_token\n            }\n        })\n        .persist()\n        //Estimates\n        .get('/v1.2/estimates/price?start_latitude=3.1357169&start_longitude=101.6881501&end_latitude=3.0831659&end_longitude=101.6505078&seat_count=2')\n        .replyWithFile(200, jp('riders/price'))\n        .get(function(uri) {\n            return uri.indexOf('v1.2/estimates/time?start_latitude=3.1357169&start_longitude=101.6881501') >= 0;\n        })\n        .replyWithFile(200, jp('riders/time'))\n        // Products\n        .get('/v1.2/products?latitude=3.1357169&longitude=101.6881501')\n        .replyWithFile(200, jp('riders/product'))\n        .get('/v1.2/products/d4abaae7-f4d6-4152-91cc-77523e8165a4')\n        .replyWithFile(200, jp('riders/productDetail'));\n\n    // Endpoints for sandbox mode with server_token\n    nock('https://sandbox-api.uber.com', {\n            reqheaders: {\n                'Authorization': 'Token ' + key.server_token\n            }\n        })\n        .persist()\n        .put('/v1.2/sandbox/products/d4abaae7-f4d6-4152-91cc-77523e8165a4', {\n            surge_multiplier: 2.2\n        })\n        .reply(204)\n        .put('/v1.2/sandbox/products/d4abaae7-f4d6-4152-91cc-77523e8165a4', {\n            drivers_available: false\n        })\n        .reply(204);\n\n    // Endpoints for sandbox mode with OAuth2 Token\n    nock('https://sandbox-api.uber.com', {\n            reqheaders: {\n                'Authorization': 'Bearer ' + jr('auth/token').access_token\n            }\n        })\n        .persist()\n        .put('/v1.2/sandbox/requests/17cb78a7-b672-4d34-a288-a6c6e44d5315', {\n            status: 'accepted'\n        })\n        .reply(204);\n\n    // Geocoder\n    nock('http://maps.googleapis.com')\n        .persist()\n        .get('/maps/api/geocode/json?sensor=false&address=A')\n        .replyWithFile(200, jp('geocoder/locationA'))\n        .get('/maps/api/geocode/json?sensor=false&address=B')\n        .replyWithFile(200, jp('geocoder/locationB'))\n        .get('/maps/api/geocode/json?sensor=false&address=C')\n        .replyWithFile(200, jp('geocoder/locationC'))\n        .get('/maps/api/geocode/json?sensor=false&address=%20')\n        .replyWithFile(200, jp('geocoder/locationEmpty'));\n};\n"
  },
  {
    "path": "test/auth/oauth.js",
    "content": "var common = require('../common'),\n  should = common.should,\n  qs = common.qs,\n  uber = common.uber,\n  reply = common.jsonReply,\n  ac = common.authCode,\n  acTE = common.authCodeTokenExpired,\n  acTNR = common.authCodeTokenNoRefresh;\n\ndescribe('OAuth2 authorization url', function() {\n  it('generate OAuth2 correct authorization url', function(done) {\n    var allScopes = [\n      'profile',\n      'history',\n      'places',\n      'request',\n      'request_receipt',\n      'all_trips',\n      'partner.payments',\n      'partner.accounts',\n      'partner.trips'\n    ];\n    var url = uber.getAuthorizeUrl(allScopes),\n      sampleUrl = uber.defaults.authorize_url + '?' + qs.stringify({response_type: 'code', redirect_uri: uber.defaults.redirect_uri, scope: allScopes.join(' '), client_id: uber.defaults.client_id});\n    url.should.equal(sampleUrl);\n    done();\n  });\n\n  it('should return error if scope is not an array', function(done) {\n    uber.getAuthorizeUrl().message.should.equal('Scope is not an array');\n    done();\n  });\n\n  it('should return error if scope is not an empty array', function(done) {\n    uber.getAuthorizeUrl([]).message.should.equal('Scope is empty');\n    done();\n  });\n});\n\ndescribe('Exchange authorization code into access token', function() {\n  it('should be able to get access token and refresh token using authorization code', function(done) {\n    uber.authorization({\n      authorization_code: ac\n    }, function(err, res) {\n      should.not.exist(err);\n      res[0].should.equal(reply('auth/token').access_token);\n      res[1].should.equal(reply('auth/token').refresh_token);\n      uber.access_token.should.equal(reply('auth/token').access_token);\n      uber.refresh_token.should.equal(reply('auth/token').refresh_token);\n      done();\n    });\n  });\n\n  it('should able to get access token and refresh token using refresh token', function(done) {\n    uber.authorization({\n      refresh_token: 'x8Y6dF2qA6iKaTKlgzVfFvyYoNrlkp'\n    }, function(err, res) {\n      should.not.exist(err);\n      res[0].should.equal(reply('auth/token').access_token);\n      res[1].should.equal(reply('auth/token').refresh_token);\n      uber.access_token.should.equal(reply('auth/token').access_token);\n      uber.refresh_token.should.equal(reply('auth/token').refresh_token);\n      done();\n    });\n  });\n\n  it('should return error if there is no authorization_code or refresh_token', function(done) {\n    uber.authorization({}, function(err, access_token, refresh_token) {\n      err.message.should.equal('No authorization_code or refresh_token');\n      done();\n    });\n  });\n\n  it('should return error if uber auth service not reachable', function(done) {\n    uber.authorization({\n      authorization_code: ''\n    }, function(err, access_token, refresh_token) {\n      err.statusCode.should.equal(500);\n      done();\n    });\n  });\n});\n\ndescribe('Auto refresh token whenever it is expired', function() {\n  it('should be able to recognize an expired token and then auto refresh the token ', function(done) {\n    uber.authorization({\n      authorization_code: acTE\n    }, function(err, res) {\n      should.not.exist(err);\n      uber.requests.create({\n        product_id: 'a1111c8c-c720-46c3-8534-2fcdd730040d',\n        start_latitude: 37.761492,\n        start_longitude: -122.423941,\n        end_latitude: 37.775393,\n        end_longitude: -122.417546\n      }, function(err, res) {\n        should.not.exist(err);\n        uber.tokenExpiration.should.be.above(new Date());\n        done();\n      });\n    });\n  });\n  it('should return an error if the uber server is not available while refreshing token', function(done) {\n    uber.authorization({\n      authorization_code: acTNR\n    }, function(err, res) {\n      should.not.exist(err);\n      uber.requests.create({\n        product_id: 'a1111c8c-c720-46c3-8534-2fcdd730040d',\n        start_latitude: 37.761492,\n        start_longitude: -122.423941,\n        end_latitude: 37.775393,\n        end_longitude: -122.417546\n      }, function(err, res) {\n        should.exist(err);\n        err.statusCode.should.equal(500);\n        done();\n      });\n    });\n  });\n});\n\ndescribe('Multi-user handling', function() {\n  it('should set Uber tokens', function(done) {\n    uber.setTokens(reply('auth/token').access_token, reply('auth/token').refresh_token, reply('auth/token').expires_in, reply('auth/token').scope);\n\n    uber.access_token.should.equal(reply('auth/token').access_token);\n    uber.refresh_token.should.equal(reply('auth/token').refresh_token);\n    uber.tokenExpiration.should.equal(reply('auth/token').expires_in);\n    uber.authorizedScopes.should.equal(reply('auth/token').scope);\n    done();\n  });\n\n  it('should clear Uber tokens', function(done) {\n    uber.setTokens(reply('auth/token').access_token, reply('auth/token').refresh_token, reply('auth/token').expires_in, reply('auth/token').scope);\n\n    uber.clearTokens();\n\n    should.not.exist(uber.access_token);\n    should.not.exist(uber.refresh_token);\n    should.not.exist(uber.tokenExpiration);\n    should.not.exist(uber.authorizedScopes);\n\n    done();\n  });\n});\n\ndescribe('OAuth2 revokeToken', function() {\n  it('should return error if token is empty', function(done) {\n    uber.revokeToken('', function(err, res) {\n      should.exist(err);\n      done();\n    });\n  });\n\n  it('should return error if token is not a string', function(done) {\n    uber.revokeToken({\n      a: 1\n    }, function(err, res) {\n      should.exist(err);\n      done();\n    });\n  });\n\n  it('should return success if token is revoked', function(done) {\n    uber.revokeToken('my_access_token', function(err, res) {\n      should.not.exist(err);\n      should.exist(res);\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "test/auth/oauthAsync.js",
    "content": "var common = require('../common'),\n  should = common.should,\n  qs = common.qs,\n  uber = common.uber,\n  reply = common.jsonReply,\n  ac = common.authCode,\n  acTE = common.authCodeTokenExpired,\n  acTNR = common.authCodeTokenNoRefresh;\n\ndescribe('Exchange authorization code into access token', function() {\n  it('should be able to get access token and refresh token using authorization code', function(done) {\n    uber.authorizationAsync({authorization_code: ac}).spread(function(access_token, refresh_token) {\n      access_token.should.equal(reply('auth/token').access_token);\n      refresh_token.should.equal(reply('auth/token').refresh_token);\n      uber.access_token.should.equal(reply('auth/token').access_token);\n      uber.refresh_token.should.equal(reply('auth/token').refresh_token);\n    }).error(function(err) {\n      should.not.exist(err);\n    });\n    done();\n  });\n\n  it('should able to get access token and refresh token using refresh token', function(done) {\n    uber.authorizationAsync({refresh_token: 'x8Y6dF2qA6iKaTKlgzVfFvyYoNrlkp'}).spread(function(access_token, refresh_token) {\n      access_token.should.equal(reply('auth/token').access_token);\n      refresh_token.should.equal(reply('auth/token').refresh_token);\n      uber.access_token.should.equal(reply('auth/token').access_token);\n      uber.refresh_token.should.equal(reply('auth/token').refresh_token);\n    }).error(function(err) {\n      should.not.exist(err);\n    });\n    done();\n  });\n\n  it('should return error if there is no authorization_code or refresh_token', function(done) {\n    uber.authorizationAsync({}).then(function(access_token, refresh_token) {\n      should.not.exist(access_token);\n      should.not.exist(refresh_token);\n    }).error(function(err) {\n      err.message.should.equal('No authorization_code or refresh_token');\n    });\n    done();\n  });\n});\n\ndescribe('Auto refresh token whenever it is expired', function() {\n  it('should be able to recognize an expired token and then auto refresh the token ', function(done) {\n    uber.authorizationAsync({authorization_code: acTE}).then(function() {\n      return uber.requests.createAsync({product_id: 'a1111c8c-c720-46c3-8534-2fcdd730040d', start_latitude: 37.761492, start_longitude: -122.423941, end_latitude: 37.775393, end_longitude: -122.417546});\n    }).then(function(res) {\n      res.should.deep.equal(reply('riders/requestCreate'));\n      uber.tokenExpiration.should.be.above(new Date());\n      done();\n    });\n  });\n  it('should return an error if the uber server is not available while refreshing token', function(done) {\n    uber.authorizationAsync({authorization_code: acTNR}).then(function() {\n      return uber.requests.createAsync({product_id: 'a1111c8c-c720-46c3-8534-2fcdd730040d', start_latitude: 37.761492, start_longitude: -122.423941, end_latitude: 37.775393, end_longitude: -122.417546});\n    }).then(function(res) {\n      should.not.exist(res);\n    }).error(function(err) {\n      should.exist(err);\n      err.statusCode.should.equal(500);\n      done();\n    });\n  });\n});\n\ndescribe('OAuth2 revokeTokenAsync', function() {\n  it('should return error if token is empty', function(done) {\n    uber.revokeTokenAsync('').then(function(res) {\n      should.not.exist(res);\n    }).error(function(err) {\n      should.exist(err);\n      done();\n    });\n  });\n\n  it('should return error if token is not a string', function(done) {\n    uber.revokeTokenAsync({a: 1}).then(function(res) {\n      should.not.exist(res);\n    }).error(function(err) {\n      should.exist(err);\n      done();\n    });\n  });\n\n  it('should return success if token is revoked', function(done) {\n    uber.revokeTokenAsync('my_access_token').then(function(res) {\n      should.exist(res);\n    }).error(function(err) {\n      should.not.exist(err);\n      done();\n    });\n    done();\n  });\n});\n"
  },
  {
    "path": "test/common.js",
    "content": "var chai = require('chai'),\n    nock = require('nock'),\n    request = require('superagent'),\n    should = chai.should(),\n    qs = require('querystring'),\n    Uber = require('../lib/Uber'),\n    path = require('path'),\n    fs = require('fs');\n\nvar key = {\n    \"client_id\": \"CLIENTIDCLIENTIDCLIENTIDCLIENT\",\n    \"client_secret\": \"CLIENTSECRETCLIENTSECRETCLIENTSECRETCLIE\",\n    \"server_token\": \"SERVERTOKENSERVERTOKENSERVERTOKENSERVERT\",\n    \"redirect_uri\": \"http://localhost/callback\",\n    \"google_maps_api_key\": process.env.GOOGLE_MAPS_API_KEY,\n    \"name\": \"nodejs uber wrapper\",\n    \"language\": \"en_US\"\n};\n\nvar uber = new Uber(key);\n\n// uber instance for Sandbox mode\nkey.sandbox = true;\nvar uber_sandbox = new Uber(key);\n\n// JSON path for reply files\njsonReplyPath = function(filename) {\n    return path.join(__dirname, '/replies/' + filename + '.json');\n}\n\n// Load JSON file from replies folder for assertions\njsonReply = function(path) {\n    return JSON.parse(fs.readFileSync(this.jsonReplyPath(path), 'utf8'));\n}\n\nexports.chai = chai;\nexports.nock = nock;\nexports.request = request;\nexports.should = should;\nexports.qs = qs;\nexports.uber = uber;\nexports.uber_sandbox = uber_sandbox;\nexports.key = key;\nexports.jsonReplyPath = jsonReplyPath;\nexports.jsonReply = jsonReply;\nexports.authCode = 'x8Y6dF2qA6iKaTKlgzVfFvyYoNrlkp';\nexports.authCodeNoProfile = 'h6Y6dF2qA6iKaTKlgzVfFvyYoNrLK3';\nexports.authCodeNoPlaces = 'j1P6dF2qA6iKaTKlgzVfFvyYoNrhU1';\nexports.authCodeNoRequest = 'a0P6dK3oA6iKaTKlgzVfFvyYoNrfG5';\nexports.authCodeTokenExpired = 'h0P6dK3aA6iKaTK4gzVfFvyYoNrfG5';\nexports.authCodeTokenNoRefresh = 'm0P6dK3aTPiKaTK4gzVfFvyYoNrfG5';\nexports.authCodeRefreshTokenError = 'Zxkcv8qdSRRseIVlshydoQ4wnZBehr';\nexports.authCodeTokenRefresh = 'Zx8fJ8qdSRRseIVlsGgtgQ4wnZBehr';\nexports.requestProductCreate = 'a1111c8c-c720-46c3-8534-2fcdd730040d';\nexports.requestProductSurge = 'a1111c8c-c720-8150-8534-2fcdd730040d';\nexports.requestProductSomeOtherError = 'a2341c8c-c720-8150-8534-2fcdd730040d';\nexports.requestSurgeConfirmationID = 'e100a670';"
  },
  {
    "path": "test/drivers/payments.js",
    "content": "var common = require(\"../common\"),\n  should = common.should,\n  uber = common.uber,\n  reply = common.jsonReply,\n  ac = common.authCode,\n  acNP = common.authCodeNoProfile;\n\nit('should get driver partner payments after authentication', function(done) {\n  uber.authorization({\n    authorization_code: ac\n  }, function(err, accessToken, refreshToken) {\n    should.not.exist(err);\n    uber.partnerpayments.getPayments(0, 50, 1451606400, 1505160819, function(err, res) {\n      should.not.exist(err);\n      res.should.deep.equal(reply('drivers/partnerPayments'));\n      done();\n    });\n  });\n});\n\nit('should get driver partner payments after authentication, even with a too high limit', function(done) {\n  uber.authorization({\n    authorization_code: ac\n  }, function(err, accessToken, refreshToken) {\n    should.not.exist(err);\n    uber.partnerpayments.getPayments(0, 99, 1451606400, 1505160819, function(err, res) {\n      should.not.exist(err);\n      res.should.deep.equal(reply('drivers/partnerPayments'));\n      done();\n    });\n  });\n});\n\nit('should get driver partner payments after authentication without required parameters', function(done) {\n  uber.authorization({\n    authorization_code: ac\n  }, function(err, accessToken, refreshToken) {\n    should.not.exist(err);\n    uber.partnerpayments.getPayments(null, null, null, null, function(err, res) {\n      should.not.exist(err);\n      res.should.deep.equal(reply('drivers/partnerPayments'));\n      done();\n    });\n  });\n});\n\nit('should return invalid access token error when no token found', function(done) {\n  uber.clearTokens();\n  uber.partnerpayments.getPayments(null, null, null, null, function(err, res) {\n    err.message.should.equal('Invalid access token');\n    done();\n  });\n});\n"
  },
  {
    "path": "test/drivers/paymentsAsync.js",
    "content": "var common = require(\"../common\"),\n  should = common.should,\n  uber = common.uber,\n  reply = common.jsonReply,\n  ac = common.authCode,\n  acNP = common.authCodeNoProfile;\n\nit('should get driver partner payments after authentication', function(done) {\n  uber.authorizationAsync({authorization_code: ac}).then(function() {\n    return uber.partnerpayments.getPaymentsAsync(0, 50, 1451606400, 1505160819);\n  }).then(function(res) {\n    res.should.deep.equal(reply('drivers/partnerPayments'));\n    done();\n  });\n});\n\nit('should get driver partner payments after authentication, even with a too high limit', function(done) {\n  uber.authorizationAsync({authorization_code: ac}).then(function() {\n    return uber.partnerpayments.getPaymentsAsync(0, 99, 1451606400, 1505160819);\n  }).then(function(res) {\n    res.should.deep.equal(reply('drivers/partnerPayments'));\n    done();\n  });\n});\n\nit('should get driver partner payments after authentication without required parameters', function(done) {\n  uber.authorizationAsync({authorization_code: ac}).then(function() {\n    return uber.partnerpayments.getPaymentsAsync(null, null, null, null);\n  }).then(function(res) {\n    res.should.deep.equal(reply('drivers/partnerPayments'));\n    done();\n  });\n});\n\nit('should return invalid access token error when no token found', function(done) {\n  uber.clearTokens();\n  uber.partnerpayments.getPaymentsAsync(null, null, null, null).error(function(err) {\n    err.message.should.equal('Invalid access token');\n    done();\n  });\n});\n"
  },
  {
    "path": "test/drivers/profile.js",
    "content": "var common = require(\"../common\"),\n  should = common.should,\n  uber = common.uber,\n  reply = common.jsonReply,\n  ac = common.authCode,\n  acNP = common.authCodeNoProfile;\n\nit('should return invalid access token error when no token found', function(done) {\n  uber.clearTokens();\n  uber.partnerprofile.getProfile(function(err, res) {\n    err.message.should.equal('Invalid access token');\n    done();\n  });\n});\n\nit('should get partner profile after authentication', function(done) {\n  uber.authorization({\n    authorization_code: ac\n  }, function(err, accessToken, refreshToken) {\n    should.not.exist(err);\n    uber.partnerprofile.getProfile(function(err, res) {\n      should.not.exist(err);\n      res.should.deep.equal(reply('drivers/partnerProfile'));\n      done();\n    });\n  });\n});\n\nit('should return error for partner profile with missing partner.accounts scope', function(done) {\n  uber.authorization({\n    authorization_code: acNP\n  }, function(err, accessToken, refreshToken) {\n    should.not.exist(err);\n    uber.partnerprofile.getProfile(function(err, res) {\n      err.message.should.equal('Required scope not found');\n      done();\n    });\n  });\n});\n"
  },
  {
    "path": "test/drivers/profileAsync.js",
    "content": "var common = require(\"../common\"),\n  should = common.should,\n  uber = common.uber,\n  reply = common.jsonReply,\n  ac = common.authCode,\n  acNP = common.authCodeNoProfile;\n\nit('should return invalid access token error when no token found', function(done) {\n  uber.clearTokens();\n  uber.partnerprofile.getProfileAsync().error(function(err) {\n    err.message.should.equal('Invalid access token');\n    done();\n  });\n});\n\nit('should get partner profile after authentication', function(done) {\n  uber.authorizationAsync({authorization_code: ac}).then(function() {\n    return uber.partnerprofile.getProfileAsync();\n  }).then(function(res) {\n    res.should.deep.equal(reply('drivers/partnerProfile'));\n    done();\n  });\n});\n\nit('should return error for partner profile with missing partner.accounts scope', function(done) {\n  uber.authorizationAsync({authorization_code: acNP}).then(function() {\n    return uber.partnerprofile.getProfileAsync();\n  }).error(function(err) {\n    err.message.should.equal('Required scope not found');\n    done();\n  });\n});\n"
  },
  {
    "path": "test/drivers/trips.js",
    "content": "var common = require(\"../common\"),\n  should = common.should,\n  uber = common.uber,\n  reply = common.jsonReply,\n  ac = common.authCode,\n  acNP = common.authCodeNoProfile;\n\nit('should get driver partner trips after authentication', function(done) {\n  uber.authorization({\n    authorization_code: ac\n  }, function(err, accessToken, refreshToken) {\n    should.not.exist(err);\n    uber.partnertrips.getTrips(0, 50, 1451606400, 1505160819, function(err, res) {\n      should.not.exist(err);\n      res.should.deep.equal(reply('drivers/partnerTrips'));\n      done();\n    });\n  });\n});\n\nit('should get driver partner trips after authentication, even with a too high limit', function(done) {\n  uber.authorization({\n    authorization_code: ac\n  }, function(err, accessToken, refreshToken) {\n    should.not.exist(err);\n    uber.partnertrips.getTrips(0, 99, 1451606400, 1505160819, function(err, res) {\n      should.not.exist(err);\n      res.should.deep.equal(reply('drivers/partnerTrips'));\n      done();\n    });\n  });\n});\n\nit('should get driver partner trips after authentication without required parameters', function(done) {\n  uber.authorization({\n    authorization_code: ac\n  }, function(err, accessToken, refreshToken) {\n    should.not.exist(err);\n    uber.partnertrips.getTrips(null, null, null, null, function(err, res) {\n      should.not.exist(err);\n      res.should.deep.equal(reply('drivers/partnerTrips'));\n      done();\n    });\n  });\n});\n\nit('should return invalid access token error when no token found', function(done) {\n  uber.clearTokens();\n  uber.partnertrips.getTrips(null, null, null, null, function(err, res) {\n    err.message.should.equal('Invalid access token');\n    done();\n  });\n});\n"
  },
  {
    "path": "test/drivers/tripsAsync.js",
    "content": "var common = require(\"../common\"),\n  should = common.should,\n  uber = common.uber,\n  reply = common.jsonReply,\n  ac = common.authCode,\n  acNP = common.authCodeNoProfile;\n\nit('should get driver partner trips after authentication', function(done) {\n  uber.authorizationAsync({authorization_code: ac}).then(function() {\n    return uber.partnertrips.getTripsAsync(0, 50, 1451606400, 1505160819);\n  }).then(function(res) {\n    res.should.deep.equal(reply('drivers/partnerTrips'));\n    done();\n  });\n});\n\nit('should get driver partner trips after authentication, even with a too high limit', function(done) {\n  uber.authorizationAsync({authorization_code: ac}).then(function() {\n    return uber.partnertrips.getTripsAsync(0, 99, 1451606400, 1505160819);\n  }).then(function(res) {\n    res.should.deep.equal(reply('drivers/partnerTrips'));\n    done();\n  });\n});\n\nit('should get driver partner trips after authentication without required parameters', function(done) {\n  uber.authorizationAsync({authorization_code: ac}).then(function() {\n    return uber.partnertrips.getTripsAsync(null, null, null, null);\n  }).then(function(res) {\n    res.should.deep.equal(reply('drivers/partnerTrips'));\n    done();\n  });\n});\n\nit('should return invalid access token error when no token found', function(done) {\n  uber.clearTokens();\n  uber.partnertrips.getTripsAsync(null, null, null, null).error(function(err) {\n    err.message.should.equal('Invalid access token');\n    done();\n  });\n});\n"
  },
  {
    "path": "test/general.js",
    "content": "var common = require(\"./common\"),\n    key = common.key,\n    uber = common.uber;\n\nit('should load the key from a key.json', function(done) {\n    key.should.have.property('client_id');\n    key.should.have.property('client_secret');\n    key.should.have.property('server_token');\n    key.should.have.property('redirect_uri');\n    key.should.have.property('name');\n    key.should.have.property('language');\n    done();\n});\n\nit('should initiate Uber client with the key', function(done) {\n    uber.should.have.property('defaults');\n    uber.defaults.language.should.equal(key.language);\n    uber.defaults.client_id.should.equal(key.client_id);\n    uber.defaults.client_secret.should.equal(key.client_secret);\n    uber.defaults.server_token.should.equal(key.server_token);\n    uber.defaults.redirect_uri.should.equal(key.redirect_uri);\n    uber.defaults.base_url.should.equal('https://api.uber.com/');\n    uber.defaults.authorize_url.should.equal('https://login.uber.com/oauth/v2/authorize');\n    uber.defaults.access_token_url.should.equal('https://login.uber.com/oauth/v2/token');\n    uber.should.have.property('oauth2');\n    done();\n});\n"
  },
  {
    "path": "test/replies/auth/token.json",
    "content": "{\n    \"access_token\": \"EE1IDxytP04tJ767GbjH7ED9PpGmYvL\",\n    \"token_type\": \"Bearer\",\n    \"expires_in\": 2592000,\n    \"refresh_token\": \"Zx8fJ8qdSRRseIVlsGgtgQ4wnZBehr\",\n    \"scope\": \"profile, history, places, request, request_receipt, all_trips, partner.payments, partner.accounts, partner.trips\"\n}\n"
  },
  {
    "path": "test/replies/auth/tokenExpired.json",
    "content": "{\n  \"access_token\": \"EE1IDxytP04tJ767GbjH7ED9PpGmYvL\",\n  \"token_type\": \"Bearer\",\n  \"expires_in\": -100,\n  \"refresh_token\": \"Zx8fJ8qdSRRseIVlsGgtgQ4wnZBehr\",\n  \"scope\": \"profile history places request request_receipt\"\n}\n"
  },
  {
    "path": "test/replies/auth/tokenNoPlaces.json",
    "content": "{\n    \"access_token\": \"EE1IDxytP04tJ767GbjH7ED9PpGmYvL\",\n    \"token_type\": \"Bearer\",\n    \"expires_in\": 2592000,\n    \"refresh_token\": \"Zx8fJ8qdSRRseIVlsGgtgQ4wnZBehr\",\n    \"scope\": \"profile history request request_receipt\"\n}\n"
  },
  {
    "path": "test/replies/auth/tokenNoProfile.json",
    "content": "{\n    \"access_token\": \"EE1IDxytP04tJ767GbjH7ED9PpGmYvL\",\n    \"token_type\": \"Bearer\",\n    \"expires_in\": 2592000,\n    \"refresh_token\": \"Zx8fJ8qdSRRseIVlsGgtgQ4wnZBehr\",\n    \"scope\": \"history places request request_receipt\"\n}\n"
  },
  {
    "path": "test/replies/auth/tokenNoRefresh.json",
    "content": "{\n  \"access_token\": \"EE1IDxytP04tJ767GbjH7ED9PpGmYvL\",\n  \"token_type\": \"Bearer\",\n  \"expires_in\": -100,\n  \"refresh_token\": \"Zxkcv8qdSRRseIVlshydoQ4wnZBehr\",\n  \"scope\": \"profile history places request request_receipt\"\n}\n"
  },
  {
    "path": "test/replies/auth/tokenNoRequest.json",
    "content": "{\n    \"access_token\": \"EE1IDxytP04tJ767GbjH7ED9PpGmYvL\",\n    \"token_type\": \"Bearer\",\n    \"expires_in\": 2592000,\n    \"refresh_token\": \"Zx8fJ8qdSRRseIVlsGgtgQ4wnZBehr\",\n    \"scope\": \"profile history places request_receipt\"\n}\n"
  },
  {
    "path": "test/replies/auth/tokenRefreshed.json",
    "content": "{\n  \"access_token\": \"EE1IDxytP04tJ767GbjH7ED9PpGmYvL\",\n  \"token_type\": \"Bearer\",\n  \"expires_in\": 2592000,\n  \"refresh_token\": \"Zx8fJ8qdSRRseIVlsGgtgQ4wnZBehr\",\n  \"scope\": \"profile history places request request_receipt\"\n}\n"
  },
  {
    "path": "test/replies/drivers/partnerPayments.json",
    "content": "{\n  \"count\": 1200,\n  \"limit\": 1,\n  \"payments\": [\n    {\n      \"payment_id\": \"5cb8304c-f3f0-4a46-b6e3-b55e020750d7\",\n      \"category\": \"fare\",\n      \"event_time\": 1502842757,\n      \"trip_id\": \"5cb8304c-f3f0-4a46-b6e3-b55e020750d7\",\n      \"cash_collected\": 0,\n      \"amount\": 4.12,\n      \"driver_id\": \"8LvWuRAq2511gmr8EMkovekFNa2848lyMaQevIto-aXmnK9oKNRtfTxYLgPq9OSt8EzAu5pDB7XiaQIrcp-zXgOA5EyK4h00U6D1o7aZpXIQah--U77Eh7LEBiksj2rahB==\",\n      \"breakdown\": {\n        \"other\": 4.16,\n        \"toll\": 1,\n        \"service_fee\": -1.04\n      },\n      \"rider_fees\": {\n        \"split_fare\": 0.50\n      },\n      \"partner_id\": \"8LvWuRAq2511gmr8EMkovekFNa2848lyMaQevIto-aXmnK9oKNRtfTxYLgPq9OSt8EzAu5pDB7XiaQIrcp-zXgOA5EyK4h00U6D1o7aZpXIQah--U77Eh7LEBiksj2rahB==\",\n      \"currency_code\": \"USD\"\n    }\n  ],\n  \"offset\": 0\n}\n"
  },
  {
    "path": "test/replies/drivers/partnerProfile.json",
    "content": "{\n  \"driver_id\": \"8LvWuRAq2511gmr8EMkovekFNa2848lyMaQevIto-aXmnK9oKNRtfTxYLgPq9OSt8EzAu5pDB7XiaQIrcp-zXgOA5EyK4h00U6D1o7aZpXIQah--U77Eh7LEBiksj2rahB==\",\n  \"first_name\": \"Uber\",\n  \"last_name\": \"Tester\",\n  \"email\": \"uber.developer+tester@example.com\",\n  \"phone_number\": \"+14155550000\",\n  \"picture\": \"https://d1w2poirtb3as9.cloudfront.net/16ce502f4767f17b120e.png\",\n  \"promo_code\": \"ubert4544ue\",\n  \"rating\": 5,\n  \"activation_status\": \"active\"\n}\n"
  },
  {
    "path": "test/replies/drivers/partnerTrips.json",
    "content": "{\n  \"count\": 1200,\n  \"limit\": 1,\n  \"trips\": [\n    {\n      \"fare\": 6.2,\n      \"dropoff\": {\n        \"timestamp\": 1502844378\n      },\n      \"vehicle_id\": \"0082b54a-6a5e-4f6b-b999-b0649f286381\",\n      \"distance\": 0.37,\n      \"start_city\": {\n        \"latitude\": 38.3498,\n        \"display_name\": \"Charleston, WV\",\n        \"longitude\": -81.6326\n      },\n      \"status_changes\": [\n        {\n          \"status\": \"accepted\",\n          \"timestamp\": 1502843899\n        },\n        {\n          \"status\": \"driver_arrived\",\n          \"timestamp\": 1502843900\n        },\n        {\n          \"status\": \"trip_began\",\n          \"timestamp\": 1502843903\n        },\n        {\n          \"status\": \"completed\",\n          \"timestamp\": 1502844378\n        }\n      ],\n      \"surge_multiplier\": 1,\n      \"pickup\": {\n        \"timestamp\": 1502843903\n      },\n      \"driver_id\": \"8LvWuRAq2511gmr8EMkovekFNa2848lyMaQevIto-aXmnK9oKNRtfTxYLgPq9OSt8EzAu5pDB7XiaQIrcp-zXgOA5EyK4h00U6D1o7aZpXIQah--U77Eh7LEBiksj2rahB==\",\n      \"status\": \"completed\",\n      \"duration\": 475,\n      \"trip_id\": \"b5613b6a-fe74-4704-a637-50f8d51a8bb1\",\n      \"currency_code\": \"USD\"\n    }\n  ],\n  \"offset\": 0\n}\n"
  },
  {
    "path": "test/replies/geocoder/locationA.json",
    "content": "{\n    \"results\": [{\n        \"geometry\": {\n            \"location\": {\n                \"lat\": 3.1357169,\n                \"lng\": 101.6881501\n            }\n        }\n    }]\n}\n"
  },
  {
    "path": "test/replies/geocoder/locationB.json",
    "content": "{\n    \"results\": [{\n        \"geometry\": {\n            \"location\": {\n                \"lat\": 3.0831659,\n                \"lng\": 101.6505078\n            }\n        }\n    }]\n}\n"
  },
  {
    "path": "test/replies/geocoder/locationC.json",
    "content": "{\n    \"results\": [{\n        \"geometry\": {\n            \"location\": {\n                \"lat\": 37.7598258,\n                \"lng\": -122.4260558\n            }\n        }\n    }]\n}\n"
  },
  {
    "path": "test/replies/geocoder/locationEmpty.json",
    "content": "{\n    \"results\": []\n}\n"
  },
  {
    "path": "test/replies/riders/history.json",
    "content": "{\n  \"count\": 15,\n  \"history\": [\n    {\n      \"status\": \"completed\",\n      \"distance\": 1.4780860317,\n      \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n      \"start_time\": 1475545183,\n      \"start_city\": {\n        \"latitude\": 37.7749,\n        \"display_name\": \"San Francisco\",\n        \"longitude\": -122.4194\n      },\n      \"end_time\": 1475545808,\n      \"request_id\": \"fb0a7c1f-2cf7-4310-bd27-8ba7737362fe\",\n      \"request_time\": 1475545095\n    },\n    {\n      \"status\": \"completed\",\n      \"distance\": 1.2792152568,\n      \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n      \"start_time\": 1475513472,\n      \"start_city\": {\n        \"latitude\": 37.7749,\n        \"display_name\": \"San Francisco\",\n        \"longitude\": -122.4194\n      },\n      \"end_time\": 1475513898,\n      \"request_id\": \"d72338b0-394d-4f0e-a73c-78d469fa0c6d\",\n      \"request_time\": 1475513393\n    },\n    {\n      \"status\": \"completed\",\n      \"distance\": 1.5084526246,\n      \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n      \"start_time\": 1475170251,\n      \"start_city\": {\n        \"latitude\": 37.7749,\n        \"display_name\": \"San Francisco\",\n        \"longitude\": -122.4194\n      },\n      \"end_time\": 1475171154,\n      \"request_id\": \"2b61e340-27bd-4937-8304-122009e4a393\",\n      \"request_time\": 1475170088\n    },\n    {\n      \"status\": \"completed\",\n      \"distance\": 1.4705337758,\n      \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n      \"start_time\": 1475027766,\n      \"start_city\": {\n        \"latitude\": 37.7749,\n        \"display_name\": \"San Francisco\",\n        \"longitude\": -122.4194\n      },\n      \"end_time\": 1475028387,\n      \"request_id\": \"58cb7b3c-fe22-47b4-94c0-2cf08b34f4be\",\n      \"request_time\": 1475027705\n    },\n    {\n      \"status\": \"completed\",\n      \"distance\": 0.6489455763,\n      \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n      \"start_time\": 1475002745,\n      \"start_city\": {\n        \"latitude\": 37.7749,\n        \"display_name\": \"San Francisco\",\n        \"longitude\": -122.4194\n      },\n      \"end_time\": 1475003150,\n      \"request_id\": \"57be6f97-e10f-411e-a87e-670011c46b55\",\n      \"request_time\": 1475002656\n    },\n    {\n      \"status\": \"completed\",\n      \"distance\": 0.6632030652,\n      \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n      \"start_time\": 1475001862,\n      \"start_city\": {\n        \"latitude\": 37.7749,\n        \"display_name\": \"San Francisco\",\n        \"longitude\": -122.4194\n      },\n      \"end_time\": 1475002218,\n      \"request_id\": \"0ca65d53-3351-4f3b-b07f-55e4fe4c1ad9\",\n      \"request_time\": 1475001534\n    },\n    {\n      \"status\": \"completed\",\n      \"distance\": 1.3935675129,\n      \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n      \"start_time\": 1474995527,\n      \"start_city\": {\n        \"latitude\": 37.7749,\n        \"display_name\": \"San Francisco\",\n        \"longitude\": -122.4194\n      },\n      \"end_time\": 1474995943,\n      \"request_id\": \"c0453d97-4330-4ec2-88ab-38678101cc0b\",\n      \"request_time\": 1474995056\n    },\n    {\n      \"status\": \"completed\",\n      \"distance\": 1.5046201975,\n      \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n      \"start_time\": 1474909791,\n      \"start_city\": {\n        \"latitude\": 37.7749,\n        \"display_name\": \"San Francisco\",\n        \"longitude\": -122.4194\n      },\n      \"end_time\": 1474910341,\n      \"request_id\": \"35822455-e4f5-4339-b763-6fc3ea16dc61\",\n      \"request_time\": 1474909743\n    },\n    {\n      \"status\": \"completed\",\n      \"distance\": 2.4445998557,\n      \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n      \"start_time\": 1474685017,\n      \"start_city\": {\n        \"latitude\": 37.7749,\n        \"display_name\": \"San Francisco\",\n        \"longitude\": -122.4194\n      },\n      \"end_time\": 1474685568,\n      \"request_id\": \"81a0ffda-a879-4443-beb8-e253f4d19ecc\",\n      \"request_time\": 1474684872\n    },\n    {\n      \"status\": \"completed\",\n      \"distance\": 1.3603866105,\n      \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n      \"start_time\": 1474651767,\n      \"start_city\": {\n        \"latitude\": 37.7749,\n        \"display_name\": \"San Francisco\",\n        \"longitude\": -122.4194\n      },\n      \"end_time\": 1474652253,\n      \"request_id\": \"97736867-41ca-432a-b7e9-909e66d833ba\",\n      \"request_time\": 1474651636\n    }\n  ],\n  \"limit\": 10,\n  \"offset\": 0\n}\n"
  },
  {
    "path": "test/replies/riders/paymentMethod.json",
    "content": "{\n  \"payment_methods\": [\n    {\n      \"payment_method_id\": \"5f384f7d-8323-4207-a297-51c571234a8c\",\n      \"type\": \"baidu_wallet\",\n      \"description\": \"***53\"\n    },\n    {\n      \"payment_method_id\": \"f33847de-8113-4587-c307-51c2d13a823c\",\n      \"type\": \"alipay\",\n      \"description\": \"ga***@uber.com\"\n    },\n    {\n      \"payment_method_id\": \"f43847de-8113-4587-c307-51c2d13a823c\",\n      \"type\": \"visa\",\n      \"description\": \"***23\"\n    },\n    {\n      \"payment_method_id\": \"517a6c29-3a2b-45cb-94a3-35d679909a71\",\n      \"type\": \"american_express\",\n      \"description\": \"***05\"\n    },\n    {\n      \"payment_method_id\": \"f53847de-8113-4587-c307-51c2d13a823c\",\n      \"type\": \"business_account\",\n      \"description\": \"Late Night Ride\"\n    }\n  ],\n  \"last_used\": \"f53847de-8113-4587-c307-51c2d13a823c\"\n}\n"
  },
  {
    "path": "test/replies/riders/placeHome.json",
    "content": "{\n   \"address\": \"685 Market St, San Francisco, CA 94103, USA\"\n}\n"
  },
  {
    "path": "test/replies/riders/placeWork.json",
    "content": "{\n   \"address\": \"685 Market St, San Francisco, CA 94103, USA\"\n}\n"
  },
  {
    "path": "test/replies/riders/price.json",
    "content": "{\n  \"prices\": [\n    {\n      \"localized_display_name\": \"POOL\",\n      \"distance\": 6.17,\n      \"display_name\": \"POOL\",\n      \"product_id\": \"26546650-e557-4a7b-86e7-6a3942445247\",\n      \"high_estimate\": 15,\n      \"low_estimate\": 13,\n      \"duration\": 1080,\n      \"estimate\": \"$13-14\",\n      \"currency_code\": \"USD\"\n    },\n    {\n      \"localized_display_name\": \"uberX\",\n      \"distance\": 6.17,\n      \"display_name\": \"uberX\",\n      \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n      \"high_estimate\": 17,\n      \"low_estimate\": 13,\n      \"duration\": 1080,\n      \"estimate\": \"$13-17\",\n      \"currency_code\": \"USD\"\n    },\n    {\n      \"localized_display_name\": \"uberXL\",\n      \"distance\": 6.17,\n      \"display_name\": \"uberXL\",\n      \"product_id\": \"821415d8-3bd5-4e27-9604-194e4359a449\",\n      \"high_estimate\": 26,\n      \"low_estimate\": 20,\n      \"duration\": 1080,\n      \"estimate\": \"$20-26\",\n      \"currency_code\": \"USD\"\n    },\n    {\n      \"localized_display_name\": \"SELECT\",\n      \"distance\": 6.17,\n      \"display_name\": \"SELECT\",\n      \"product_id\": \"57c0ff4e-1493-4ef9-a4df-6b961525cf92\",\n      \"high_estimate\": 38,\n      \"low_estimate\": 30,\n      \"duration\": 1080,\n      \"estimate\": \"$30-38\",\n      \"currency_code\": \"USD\"\n    },\n    {\n      \"localized_display_name\": \"BLACK\",\n      \"distance\": 6.17,\n      \"display_name\": \"BLACK\",\n      \"product_id\": \"d4abaae7-f4d6-4152-91cc-77523e8165a4\",\n      \"high_estimate\": 43,\n      \"low_estimate\": 43,\n      \"duration\": 1080,\n      \"estimate\": \"$43.10\",\n      \"currency_code\": \"USD\"\n    },\n    {\n      \"localized_display_name\": \"SUV\",\n      \"distance\": 6.17,\n      \"display_name\": \"SUV\",\n      \"product_id\": \"8920cb5e-51a4-4fa4-acdf-dd86c5e18ae0\",\n      \"high_estimate\": 63,\n      \"low_estimate\": 50,\n      \"duration\": 1080,\n      \"estimate\": \"$50-63\",\n      \"currency_code\": \"USD\"\n    },\n    {\n      \"localized_display_name\": \"ASSIST\",\n      \"distance\": 6.17,\n      \"display_name\": \"ASSIST\",\n      \"product_id\": \"ff5ed8fe-6585-4803-be13-3ca541235de3\",\n      \"high_estimate\": 17,\n      \"low_estimate\": 13,\n      \"duration\": 1080,\n      \"estimate\": \"$13-17\",\n      \"currency_code\": \"USD\"\n    },\n    {\n      \"localized_display_name\": \"WAV\",\n      \"distance\": 6.17,\n      \"display_name\": \"WAV\",\n      \"product_id\": \"2832a1f5-cfc0-48bb-ab76-7ea7a62060e7\",\n      \"high_estimate\": 33,\n      \"low_estimate\": 25,\n      \"duration\": 1080,\n      \"estimate\": \"$25-33\",\n      \"currency_code\": \"USD\"\n    },\n    {\n      \"localized_display_name\": \"TAXI\",\n      \"distance\": 6.17,\n      \"display_name\": \"TAXI\",\n      \"product_id\": \"3ab64887-4842-4c8e-9780-ccecd3a0391d\",\n      \"high_estimate\": null,\n      \"low_estimate\": null,\n      \"duration\": 1080,\n      \"estimate\": \"Metered\",\n      \"currency_code\": null\n    }\n  ]\n}\n"
  },
  {
    "path": "test/replies/riders/product.json",
    "content": "{\n  \"products\": [\n    {\n      \"upfront_fare_enabled\": true,\n      \"capacity\": 2,\n      \"product_id\": \"26546650-e557-4a7b-86e7-6a3942445247\",\n      \"image\": \"http://d1a3f4spazzrp4.cloudfront.net/car-types/mono/mono-uberx.png\",\n      \"cash_enabled\": false,\n      \"shared\": true,\n      \"short_description\": \"POOL\",\n      \"display_name\": \"POOL\",\n      \"product_group\": \"rideshare\",\n      \"description\": \"Share the ride, split the cost.\"\n    },\n    {\n      \"upfront_fare_enabled\": true,\n      \"capacity\": 4,\n      \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n      \"image\": \"http://d1a3f4spazzrp4.cloudfront.net/car-types/mono/mono-uberx.png\",\n      \"cash_enabled\": false,\n      \"shared\": false,\n      \"short_description\": \"uberX\",\n      \"display_name\": \"uberX\",\n      \"product_group\": \"uberx\",\n      \"description\": \"THE LOW-COST UBER\"\n    },\n    {\n      \"upfront_fare_enabled\": true,\n      \"capacity\": 6,\n      \"product_id\": \"821415d8-3bd5-4e27-9604-194e4359a449\",\n      \"image\": \"http://d1a3f4spazzrp4.cloudfront.net/car-types/mono/mono-uberxl2.png\",\n      \"cash_enabled\": false,\n      \"shared\": false,\n      \"short_description\": \"uberXL\",\n      \"display_name\": \"uberXL\",\n      \"product_group\": \"uberxl\",\n      \"description\": \"LOW-COST RIDES FOR LARGE GROUPS\"\n    },\n    {\n      \"upfront_fare_enabled\": true,\n      \"capacity\": 4,\n      \"product_id\": \"57c0ff4e-1493-4ef9-a4df-6b961525cf92\",\n      \"image\": \"http://d1a3f4spazzrp4.cloudfront.net/car-types/mono/mono-uberselect.png\",\n      \"cash_enabled\": false,\n      \"shared\": false,\n      \"short_description\": \"SELECT\",\n      \"display_name\": \"SELECT\",\n      \"product_group\": \"uberx\",\n      \"description\": \"A STEP ABOVE THE EVERY DAY\"\n    },\n    {\n      \"upfront_fare_enabled\": true,\n      \"capacity\": 4,\n      \"product_id\": \"d4abaae7-f4d6-4152-91cc-77523e8165a4\",\n      \"image\": \"http://d1a3f4spazzrp4.cloudfront.net/car-types/mono/mono-black.png\",\n      \"cash_enabled\": false,\n      \"shared\": false,\n      \"short_description\": \"BLACK\",\n      \"display_name\": \"BLACK\",\n      \"product_group\": \"uberblack\",\n      \"description\": \"THE ORIGINAL UBER\"\n    },\n    {\n      \"upfront_fare_enabled\": true,\n      \"capacity\": 6,\n      \"product_id\": \"8920cb5e-51a4-4fa4-acdf-dd86c5e18ae0\",\n      \"image\": \"http://d1a3f4spazzrp4.cloudfront.net/car-types/mono/mono-suv.png\",\n      \"cash_enabled\": false,\n      \"shared\": false,\n      \"short_description\": \"SUV\",\n      \"display_name\": \"SUV\",\n      \"product_group\": \"suv\",\n      \"description\": \"ROOM FOR EVERYONE\"\n    },\n    {\n      \"upfront_fare_enabled\": true,\n      \"capacity\": 4,\n      \"product_id\": \"ff5ed8fe-6585-4803-be13-3ca541235de3\",\n      \"image\": \"http://d1a3f4spazzrp4.cloudfront.net/car-types/mono/mono-uberx.png\",\n      \"cash_enabled\": false,\n      \"shared\": false,\n      \"short_description\": \"ASSIST\",\n      \"display_name\": \"ASSIST\",\n      \"product_group\": \"uberx\",\n      \"description\": \"uberX with extra assistance\"\n    },\n    {\n      \"upfront_fare_enabled\": true,\n      \"capacity\": 4,\n      \"product_id\": \"2832a1f5-cfc0-48bb-ab76-7ea7a62060e7\",\n      \"image\": \"http://d1a3f4spazzrp4.cloudfront.net/car-types/mono/mono-wheelchair.png\",\n      \"cash_enabled\": false,\n      \"shared\": false,\n      \"short_description\": \"WAV\",\n      \"display_name\": \"WAV\",\n      \"product_group\": \"uberx\",\n      \"description\": \"WHEELCHAIR ACCESSIBLE VEHICLES\"\n    },\n    {\n      \"upfront_fare_enabled\": false,\n      \"capacity\": 4,\n      \"product_id\": \"3ab64887-4842-4c8e-9780-ccecd3a0391d\",\n      \"image\": \"http://d1a3f4spazzrp4.cloudfront.net/car-types/mono/mono-taxi.png\",\n      \"cash_enabled\": false,\n      \"shared\": false,\n      \"short_description\": \"TAXI\",\n      \"display_name\": \"TAXI\",\n      \"product_group\": \"taxi\",\n      \"description\": \"TAXI WITHOUT THE HASSLE\"\n    }\n  ]\n}\n"
  },
  {
    "path": "test/replies/riders/productDetail.json",
    "content": "{\n  \"upfront_fare_enabled\": false,\n  \"capacity\": 4,\n  \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n  \"price_details\": {\n    \"service_fees\": [\n      {\n        \"fee\": 1.55,\n        \"name\": \"Booking fee\"\n      }\n    ],\n    \"cost_per_minute\": 0.22,\n    \"distance_unit\": \"mile\",\n    \"minimum\": 6.55,\n    \"cost_per_distance\": 1.15,\n    \"base\": 2,\n    \"cancellation_fee\": 5,\n    \"currency_code\": \"USD\"\n  },\n  \"image\": \"http://d1a3f4spazzrp4.cloudfront.net/car-types/mono/mono-uberx.png\",\n  \"cash_enabled\": false,\n  \"shared\": false,\n  \"short_description\": \"uberX\",\n  \"display_name\": \"uberX\",\n  \"product_group\": \"uberx\",\n  \"description\": \"THE LOW-COST UBER\"\n}\n"
  },
  {
    "path": "test/replies/riders/profile.json",
    "content": "{\n  \"picture\": \"https://d1w2poirtb3as9.cloudfront.net/f3be498cb0bbf570aa3d.jpeg\",\n  \"first_name\": \"Uber\",\n  \"last_name\": \"Developer\",\n  \"uuid\": \"f4a416e3-6016-4623-8ec9-d5ee105a6e27\",\n  \"rider_id\": \"8OlTlUG1TyeAQf1JiBZZdkKxuSSOUwu2IkO0Hf9d2HV52Pm25A0NvsbmbnZr85tLVi-s8CckpBK8Eq0Nke4X-no3AcSHfeVh6J5O6LiQt5LsBZDSi4qyVUdSLeYDnTtirw==\",\n  \"email\": \"uberdevelopers@gmail.com\",\n  \"mobile_verified\": true,\n  \"promo_code\": \"uberd340ue\"\n}\n"
  },
  {
    "path": "test/replies/riders/profilePromoError.json",
    "content": "{\n   \"meta\": {},\n   \"errors\":[\n      {\n         \"status\": 400,\n         \"code\": \"promotion_code_invalid\",\n         \"title\": \"The promotion code is not valid.\"\n      }\n   ]\n}\n"
  },
  {
    "path": "test/replies/riders/profilePromoSuccess.json",
    "content": "{\n  \"promotion_code\": \"FREE_RIDEZ\",\n  \"description\": \"$20.00 off your next ride.\"\n}\n"
  },
  {
    "path": "test/replies/riders/requestAccept.json",
    "content": "{\n  \"product_id\": \"17cb78a7-b672-4d34-a288-a6c6e44d5315\",\n  \"request_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n  \"status\": \"accepted\",\n  \"surge_multiplier\": 1.0,\n  \"shared\": true,\n  \"driver\": {\n    \"phone_number\": \"+14155550000\",\n    \"sms_number\": \"+14155550000\",\n    \"rating\": 5,\n    \"picture_url\": \"https:\\/\\/d1w2poirtb3as9.cloudfront.net\\/img.jpeg\",\n    \"name\": \"Bob\"\n  },\n  \"vehicle\": {\n    \"make\": \"Bugatti\",\n    \"model\": \"Veyron\",\n    \"license_plate\": \"I<3Uber\",\n    \"picture_url\": \"https:\\/\\/d1w2poirtb3as9.cloudfront.net\\/car.jpeg\"\n  },\n  \"location\": {\n    \"latitude\": 37.3382129093,\n    \"longitude\": -121.8863287568,\n    \"bearing\": 328\n  },\n  \"pickup\": {\n    \"alias\": \"work\",\n    \"latitude\": 37.3303463,\n    \"longitude\": -121.8890484,\n    \"name\": \"1455 Market St.\",\n    \"address\": \"1455 Market St, San Francisco, California 94103, US\",\n    \"eta\": 5\n  },\n  \"destination\": {\n    \"alias\": \"home\",\n    \"latitude\": 37.6213129,\n    \"longitude\": -122.3789554,\n    \"name\": \"685 Market St.\",\n    \"address\": \"685 Market St, San Francisco, CA 94103, USA\",\n    \"eta\": 19\n  },\n  \"waypoints\": [\n    {\n       \"rider_id\":null,\n       \"latitude\":37.77508531,\n       \"type\":\"pickup\",\n       \"longitude\":-122.3976683872\n    },\n    {\n       \"rider_id\":null,\n       \"latitude\":37.773133,\n       \"type\":\"dropoff\",\n       \"longitude\":-122.415069\n    },\n    {\n       \"rider_id\":\"8KwsIO_YG6Y2jijSMf\",\n       \"latitude\":37.7752423,\n       \"type\":\"dropoff\",\n       \"longitude\":-122.4175658\n    }\n  ],\n  \"riders\": [\n    {\n       \"rider_id\":\"8KwsIO_YG6Y2jijSMf\",\n       \"first_name\":\"Alec\",\n       \"me\": true\n    },\n    {\n       \"rider_id\":null,\n       \"first_name\":\"Kevin\",\n       \"me\": false\n    }\n  ]\n}\n"
  },
  {
    "path": "test/replies/riders/requestCreate.json",
    "content": "{\n   \"request_id\": \"852b8fdd-4369-4659-9628-e122662ad257\",\n   \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\",\n   \"status\": \"processing\",\n   \"vehicle\": null,\n   \"driver\": null,\n   \"location\": null,\n   \"eta\": 5,\n   \"surge_multiplier\": null\n}\n"
  },
  {
    "path": "test/replies/riders/requestEstimate.json",
    "content": "{\n  \"fare\": {\n    \"value\": 5.73,\n    \"fare_id\": \"d30e732b8bba22c9cdc10513ee86380087cb4a6f89e37ad21ba2a39f3a1ba960\",\n    \"expires_at\": 1476953293,\n    \"display\": \"$5.73\",\n    \"currency_code\": \"USD\",\n    \"breakdown\": [\n     {\n       \"type\": \"promotion\",\n       \"value\": -2.00,\n       \"name\": \"Promotion\"\n     },\n     {\n       \"type\": \"base_fare\",\n       \"notice\": \"Fares are slightly higher due to increased demand\",\n       \"value\": 7.73,\n       \"name\": \"Base Fare\"\n     }\n   ]\n  },\n  \"trip\": {\n    \"distance_unit\": \"mile\",\n    \"duration_estimate\": 540,\n    \"distance_estimate\": 2.39\n  },\n  \"pickup_estimate\": 2\n}\n"
  },
  {
    "path": "test/replies/riders/requestFareExpired.json",
    "content": "{\n  \"meta\": {\n    \"fare_expired\": {\n\n    }\n  },\n  \"errors\":[\n    {\n      \"status\": 409,\n      \"code\": \"fare_expired\",\n      \"title\": \"The fare has expired for the requested product.\"\n    }\n  ]\n}"
  },
  {
    "path": "test/replies/riders/requestMap.json",
    "content": "{\n    \"request_id\": \"b5512127-a134-4bf4-b1ba-fe9f48f56d9d\",\n    \"href\": \"https://trip.uber.com/abc123\"\n}\n"
  },
  {
    "path": "test/replies/riders/requestReceipt.json",
    "content": "{\n    \"request_id\": \"b5512127-a134-4bf4-b1ba-fe9f48f56d9d\",\n    \"charges\": [{\n        \"name\": \"Base Fare\",\n        \"amount\": \"2.20\",\n        \"type\": \"base_fare\"\n    }, {\n        \"name\": \"Distance\",\n        \"amount\": \"2.75\",\n        \"type\": \"distance\"\n    }, {\n        \"name\": \"Time\",\n        \"amount\": \"3.57\",\n        \"type\": \"time\"\n    }],\n    \"surge_charge\": {\n        \"name\": \"Surge x1.5\",\n        \"amount\": \"4.26\",\n        \"type\": \"surge\"\n    },\n    \"charge_adjustments\": [{\n        \"name\": \"Promotion\",\n        \"amount\": \"-2.43\",\n        \"type\": \"promotion\"\n    }, {\n        \"name\": \"Booking Fee\",\n        \"amount\": \"1.00\",\n        \"type\": \"booking_fee\"\n    }, {\n        \"name\": \"Rounding Down\",\n        \"amount\": \"0.78\",\n        \"type\": \"rounding_down\"\n    }],\n    \"normal_fare\": \"$8.52\",\n    \"subtotal\": \"$12.78\",\n    \"total_charged\": \"$5.92\",\n    \"total_owed\": null,\n    \"currency_code\": \"USD\",\n    \"duration\": \"00:11:35\",\n    \"distance\": \"1.49\",\n    \"distance_label\": \"miles\"\n}\n"
  },
  {
    "path": "test/replies/riders/requestSurge.json",
    "content": "{\n  \"meta\": {\n    \"surge_confirmation\": {\n      \"href\": \"https:\\/\\/api.uber.com\\/v1\\/surge-confirmations\\/e100a670\",\n      \"surge_confirmation_id\": \"e100a670\",\n      \"multiplier\": 1.4,\n      \"expires_at\": 1459191276\n    }\n  },\n  \"errors\":[\n    {\n      \"status\": 409,\n      \"code\": \"surge\",\n      \"title\": \"Surge pricing is currently in effect for this product.\"\n    }\n  ]\n}"
  },
  {
    "path": "test/replies/riders/time.json",
    "content": "{\n  \"times\": [\n    {\n      \"localized_display_name\": \"POOL\",\n      \"estimate\": 60,\n      \"display_name\": \"POOL\",\n      \"product_id\": \"26546650-e557-4a7b-86e7-6a3942445247\"\n    },\n    {\n      \"localized_display_name\": \"uberX\",\n      \"estimate\": 60,\n      \"display_name\": \"uberX\",\n      \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\"\n    },\n    {\n      \"localized_display_name\": \"uberXL\",\n      \"estimate\": 240,\n      \"display_name\": \"uberXL\",\n      \"product_id\": \"821415d8-3bd5-4e27-9604-194e4359a449\"\n    },\n    {\n      \"localized_display_name\": \"SELECT\",\n      \"estimate\": 240,\n      \"display_name\": \"SELECT\",\n      \"product_id\": \"57c0ff4e-1493-4ef9-a4df-6b961525cf92\"\n    },\n    {\n      \"localized_display_name\": \"BLACK\",\n      \"estimate\": 240,\n      \"display_name\": \"BLACK\",\n      \"product_id\": \"d4abaae7-f4d6-4152-91cc-77523e8165a4\"\n    },\n    {\n      \"localized_display_name\": \"SUV\",\n      \"estimate\": 240,\n      \"display_name\": \"SUV\",\n      \"product_id\": \"8920cb5e-51a4-4fa4-acdf-dd86c5e18ae0\"\n    },\n    {\n      \"localized_display_name\": \"ASSIST\",\n      \"estimate\": 300,\n      \"display_name\": \"ASSIST\",\n      \"product_id\": \"ff5ed8fe-6585-4803-be13-3ca541235de3\"\n    },\n    {\n      \"localized_display_name\": \"TAXI\",\n      \"estimate\": 480,\n      \"display_name\": \"TAXI\",\n      \"product_id\": \"3ab64887-4842-4c8e-9780-ccecd3a0391d\"\n    }\n  ]\n}\n"
  },
  {
    "path": "test/riders/estimates.js",
    "content": "var common = require(\"../common\"),\n    should = common.should,\n    uber = common.uber,\n    reply = common.jsonReply,\n    ac = common.authCode;\n\ndescribe('Price', function() {\n    it('should list all the price estimates by address', function(done) {\n        uber.estimates.getPriceForRouteByAddress('A', 'B',\n            function(err, res) {\n                should.not.exist(err);\n                res.should.deep.equal(reply('riders/price'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates by address with invalid seats count', function(done) {\n        uber.estimates.getPriceForRouteByAddress('A', 'B', '',\n            function(err, res) {\n                should.not.exist(err);\n                res.should.deep.equal(reply('riders/price'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates', function(done) {\n        uber.estimates.getPriceForRoute(3.1357169, 101.6881501, 3.0831659, 101.6505078,\n            function(err, res) {\n                should.not.exist(err);\n                res.should.deep.equal(reply('riders/price'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates with invalid seats count', function(done) {\n        uber.estimates.getPriceForRoute(3.1357169, 101.6881501, 3.0831659, 101.6505078, '',\n            function(err, res) {\n                should.not.exist(err);\n                res.should.deep.equal(reply('riders/price'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates by address without access token', function(done) {\n        uber.clearTokens();\n        uber.estimates.getPriceForRouteByAddress(\n            'A',\n            'B',\n            function(err, res) {\n                should.not.exist(err);\n                res.should.deep.equal(reply('riders/price'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates without access token', function(done) {\n        uber.clearTokens();\n        uber.estimates.getPriceForRoute(3.1357169, 101.6881501, 3.0831659, 101.6505078,\n            function(err, res) {\n                should.not.exist(err);\n                res.should.deep.equal(reply('riders/price'));\n                done();\n            });\n    });\n\n    it('should return error if start address is invalid', function(done) {\n        uber.estimates.getPriceForRouteByAddress(\n            ' ',\n            'B',\n            function(err, res) {\n                err.message.should.equal('No coordinates found for: \" \"');\n                done();\n            });\n    });\n\n    it('should return error if start address is invalid with seats', function(done) {\n        uber.estimates.getPriceForRouteByAddress(\n            ' ',\n            'B',\n            2,\n            function(err, res) {\n                err.message.should.equal('No coordinates found for: \" \"');\n                done();\n            });\n    });\n\n    it('should return error if start point lat and lon are invalid', function(done) {\n        uber.estimates.getPriceForRoute(null, null, 3.1357169, 101.6881501, function(err, res) {\n            err.message.should.equal('Invalid starting point latitude & longitude');\n            done();\n        });\n    });\n\n    it('should return error if end address is invalid', function(done) {\n        uber.estimates.getPriceForRouteByAddress(\n            'A',\n            null,\n            function(err, res) {\n                err.message.should.equal('Geocoder.geocode requires a location.');\n                done();\n            });\n    });\n\n    it('should return error if end address is invalid with seats', function(done) {\n        uber.estimates.getPriceForRouteByAddress(\n            'A',\n            null,\n            2,\n            function(err, res) {\n                err.message.should.equal('Geocoder.geocode requires a location.');\n                done();\n            });\n    });\n\n    it('should return error if end point lat and lon are invalid', function(done) {\n        uber.estimates.getPriceForRoute(3.1357169, 101.6881501, null, null, function(err, res) {\n            err.message.should.equal('Invalid ending point latitude & longitude');\n            done();\n        });\n    });\n\n    it('should return error if both addresses are null', function(done) {\n        uber.estimates.getPriceForRouteByAddress(\n            null,\n            null,\n            function(err, res) {\n                err.message.should.equal('Geocoder.geocode requires a location.');\n                done();\n            });\n    });\n\n    it('should return error if both addresses are invalid', function(done) {\n        uber.estimates.getPriceForRouteByAddress(\n            ' ',\n            ' ',\n            function(err, res) {\n                err.message.should.equal('No coordinates found for: \" \"');\n                done();\n            });\n    });\n\n    it('should return error if there is no required params', function(done) {\n        uber.estimates.getPriceForRoute(null, null, null, null, function(err, res) {\n            err.message.should.equal('Invalid starting point latitude & longitude');\n            done();\n        });\n    });\n});\n\ndescribe('Time', function() {\n    it('should list all the price estimates for location', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.estimates.getETAForLocation(3.1357169, 101.6881501,\n                    function(err, res) {\n                        should.not.exist(err);\n                        res.should.deep.equal(reply('riders/time'));\n                        done();\n                    });\n            });\n    });\n\n    it('should list all the price estimates for address', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.estimates.getETAForAddress(\n                    'A',\n                    function(err, res) {\n                        should.not.exist(err);\n                        res.should.deep.equal(reply('riders/time'));\n                        done();\n                    });\n            });\n    });\n\n    it('should list all the price estimates for location without access token', function(done) {\n        uber.clearTokens();\n        uber.estimates.getETAForLocation(3.1357169, 101.6881501,\n            function(err, res) {\n                should.not.exist(err);\n                res.should.deep.equal(reply('riders/time'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates for address without access token', function(done) {\n        uber.estimates.getETAForAddress(\n            'A',\n            function(err, res) {\n                should.not.exist(err);\n                res.should.deep.equal(reply('riders/time'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates for product and location', function(done) {\n        uber.estimates.getETAForLocation(3.1357169, 101.6881501, '327f7914-cd12-4f77-9e0c-b27bac580d03',\n            function(err, res) {\n                should.not.exist(err);\n                res.should.deep.equal(reply('riders/time'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates for product and address', function(done) {\n        uber.estimates.getETAForAddress(\n            'A',\n            '327f7914-cd12-4f77-9e0c-b27bac580d03',\n            function(err, res) {\n                should.not.exist(err);\n                res.should.deep.equal(reply('riders/time'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates for location with empty product', function(done) {\n        uber.estimates.getETAForLocation(3.1357169, 101.6881501, '',\n            function(err, res) {\n                should.not.exist(err);\n                res.should.deep.equal(reply('riders/time'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates for address with empty product', function(done) {\n        uber.estimates.getETAForAddress(\n            'A',\n            '',\n            function(err, res) {\n                should.not.exist(err);\n                res.should.deep.equal(reply('riders/time'));\n                done();\n            });\n    });\n\n    it('should return error if there is no required params', function(done) {\n        uber.estimates.getETAForLocation(null, null, function(err, res) {\n            err.message.should.equal('Invalid latitude & longitude');\n            done();\n        });\n    });\n\n    it('should return error if there is no valid address', function(done) {\n        uber.estimates.getETAForAddress(' ', function(err, res) {\n            err.message.should.equal('No coordinates found for: \" \"');\n            done();\n        });\n    });\n\n    it('should return error if there is no valid address but product_id', function(done) {\n        uber.estimates.getETAForAddress(' ', '327f7914-cd12-4f77-9e0c-b27bac580d03', function(err, res) {\n            err.message.should.equal('No coordinates found for: \" \"');\n            done();\n        });\n    });\n\n    it('should return error if there is no required params', function(done) {\n        uber.estimates.getETAForAddress(null, function(err, res) {\n            err.message.should.equal('Geocoder.geocode requires a location.');\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/riders/estimatesAsync.js",
    "content": "var common = require(\"../common\"),\n    should = common.should,\n    uber = common.uber,\n    reply = common.jsonReply,\n    ac = common.authCode;\n\ndescribe('Price', function() {\n    it('should list all the price estimates by address', function(done) {\n        uber.estimates.getPriceForRouteByAddressAsync('A', 'B')\n        .then(function(res) {\n                res.should.deep.equal(reply('riders/price'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates by address with invalid seats count', function(done) {\n        uber.estimates.getPriceForRouteByAddressAsync('A', 'B', '')\n        .then(function(res) {\n                res.should.deep.equal(reply('riders/price'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates from server', function(done) {\n        uber.estimates.getPriceForRouteAsync(3.1357169, 101.6881501, 3.0831659, 101.6505078)\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/price'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates from server with invalid seats count', function(done) {\n        uber.estimates.getPriceForRouteAsync(3.1357169, 101.6881501, 3.0831659, 101.6505078, '')\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/price'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates by address without access token', function(done) {\n        uber.clearTokens();\n        uber.estimates.getPriceForRouteByAddressAsync('A', 'B')\n        .then(function(res) {\n                res.should.deep.equal(reply('riders/price'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates from server without access token', function(done) {\n        uber.clearTokens();\n        uber.estimates.getPriceForRouteAsync(3.1357169, 101.6881501, 3.0831659, 101.6505078)\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/price'));\n                done();\n            });\n    });\n\n    it('should return error if start address is invalid', function(done) {\n        uber.estimates.getPriceForRouteByAddressAsync(' ', 'B')\n        .error(function(err) {\n                err.message.should.equal('No coordinates found for: \" \"');\n                done();\n            });\n    });\n\n    it('should return error if start address is invalid with seats', function(done) {\n        uber.estimates.getPriceForRouteByAddressAsync(' ', 'B', 2)\n        .error(function(err) {\n                err.message.should.equal('No coordinates found for: \" \"');\n                done();\n            });\n    });\n\n    it('should return error if start point lat and lon are invalid', function(done) {\n        uber.estimates.getPriceForRouteAsync(null, null, 3.1357169, 101.6881501)\n            .error(function(err) {\n                err.message.should.equal('Invalid starting point latitude & longitude');\n                done();\n            });\n    });\n\n    it('should return error if end address is invalid', function(done) {\n        uber.estimates.getPriceForRouteByAddressAsync('A', null)\n        .error(function(err) {\n                err.message.should.equal('Geocoder.geocode requires a location.');\n                done();\n            });\n    });\n\n    it('should return error if end address is invalid with seats', function(done) {\n        uber.estimates.getPriceForRouteByAddressAsync('A', null, 2)\n        .error(function(err) {\n                err.message.should.equal('Geocoder.geocode requires a location.');\n                done();\n            });\n    });\n\n    it('should return error if end point lat and lon are invalid', function(done) {\n        uber.estimates.getPriceForRouteAsync(3.1357169, 101.6881501, null, null)\n            .error(function(err) {\n                err.message.should.equal('Invalid ending point latitude & longitude');\n                done();\n            });\n    });\n\n    it('should return error if both addresses are null', function(done) {\n        uber.estimates.getPriceForRouteByAddressAsync(null, null)\n        .error(function(err) {\n                err.message.should.equal('Geocoder.geocode requires a location.');\n                done();\n            });\n    });\n\n    it('should return error if both addresses are invalid', function(done) {\n        uber.estimates.getPriceForRouteByAddressAsync(' ', ' ')\n        .error(function(err) {\n                err.message.should.equal('No coordinates found for: \" \"');\n                done();\n            });\n    });\n\n    it('should return error if there is no required params', function(done) {\n        uber.estimates.getPriceForRouteAsync(null, null, null, null)\n            .error(function(err) {\n                err.message.should.equal('Invalid starting point latitude & longitude');\n                done();\n            });\n    });\n});\n\ndescribe('Time', function() {\n    it('should list all the price estimates for location', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            }).then(function(res) {\n                return uber.estimates.getETAForLocationAsync(3.1357169, 101.6881501);\n            })\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/time'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates for address', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            }).then(function(res) {\n                return uber.estimates.getETAForAddressAsync('A');\n            })\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/time'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates for location without access token', function(done) {\n        uber.clearTokens();\n        uber.estimates.getETAForLocationAsync(3.1357169, 101.6881501)\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/time'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates for adddress without access token', function(done) {\n        uber.clearTokens();\n        uber.estimates.getETAForAddressAsync('A')\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/time'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates for product and location', function(done) {\n        uber.estimates.getETAForLocationAsync(3.1357169, 101.6881501, '327f7914-cd12-4f77-9e0c-b27bac580d03')\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/time'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates for product and address', function(done) {\n        uber.estimates.getETAForAddressAsync('A', '327f7914-cd12-4f77-9e0c-b27bac580d03')\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/time'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates for location but empty product', function(done) {\n        uber.estimates.getETAForLocationAsync(3.1357169, 101.6881501, '')\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/time'));\n                done();\n            });\n    });\n\n    it('should list all the price estimates for address but empty product', function(done) {\n        uber.estimates.getETAForAddressAsync('A', '')\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/time'));\n                done();\n            });\n    });\n\n    it('should return error if there is no required params', function(done) {\n        uber.estimates.getETAForLocationAsync(null, null)\n            .error(function(err) {\n                err.message.should.equal('Invalid latitude & longitude');\n            });\n        done();\n    });\n\n    it('should return error if there is no valid address', function(done) {\n        uber.estimates.getETAForAddressAsync(' ')\n        .error(function(err) {\n            err.message.should.equal('No coordinates found for: \" \"');\n            done();\n        });\n    });\n\n    it('should return error if there is no valid address but product_id', function(done) {\n        uber.estimates.getETAForAddressAsync(' ', '327f7914-cd12-4f77-9e0c-b27bac580d03')\n        .error(function(err) {\n            err.message.should.equal('No coordinates found for: \" \"');\n            done();\n        });\n    });\n\n    it('should return error if there is no required params', function(done) {\n        uber.estimates.getETAForAddressAsync(null)\n        .error(function(err) {\n            err.message.should.equal('Geocoder.geocode requires a location.');\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/riders/payment-methods.js",
    "content": "var common = require(\"../common\"),\n    should = common.should,\n    uber = common.uber,\n    reply = common.jsonReply,\n    ac = common.authCode;\n\nit('should list the payment methods after authentication', function(done) {\n    uber.authorization({\n            authorization_code: ac\n        },\n        function(err, accessToken, refreshToken) {\n            should.not.exist(err);\n            uber.payment.getMethods(function(err, res) {\n                should.not.exist(err);\n                res.should.deep.equal(reply('riders/paymentMethod'));\n                done();\n            });\n        });\n});\n\nit('should return invalid access token error when no token found', function(done) {\n    uber.clearTokens();\n    uber.payment.getMethods(function(err, res) {\n        err.message.should.equal('Invalid access token');\n        done();\n    });\n});\n"
  },
  {
    "path": "test/riders/payment-methodsAsync.js",
    "content": "var common = require(\"../common\"),\n    nock = common.nock,\n    should = common.should,\n    uber = common.uber,\n    reply = common.jsonReply,\n    ac = common.authCode;\n\nit('should list the payment methods after authentication', function(done) {\n    uber.authorizationAsync({\n            authorization_code: ac\n        })\n        .then(function(accessToken, refreshToken) {\n            return uber.payment.getMethodsAsync();\n        })\n        .then(function(res) {\n            res.should.deep.equal(reply('riders/paymentMethod'));\n        })\n        .error(function(err) {\n            should.not.exist(err);\n        });\n    done();\n});\n\nit('should return invalid access token error when no token found', function(done) {\n    uber.clearTokens();\n    uber.payment.getMethodsAsync()\n        .then(function(res) {\n            should.not.exist(res);\n        })\n        .error(function(err) {\n            err.message.should.equal('Invalid access token');\n        });\n    done();\n});\n"
  },
  {
    "path": "test/riders/places.js",
    "content": "var common = require(\"../common\"),\n    should = common.should,\n    uber = common.uber,\n    reply = common.jsonReply,\n    ac = common.authCode,\n    acNPl = common.authCodeNoPlaces;\n\ndescribe('Home', function() {\n    it('should return error for missing access token', function(done) {\n        uber.clearTokens();\n        uber.places.updateHome('685 Market St, San Francisco, CA 94103, USA', function(err, res) {\n            err.message.should.equal('Invalid access token');\n            done();\n        });\n    });\n\n    it('should list the home address after authentication', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.places.getHome(function(err, res) {\n                    should.not.exist(err);\n                    res.should.deep.equal(reply('riders/placeHome'));\n                    done();\n                });\n            });\n    });\n\n    it('should return invalid access token error when no token found', function(done) {\n\n        uber.clearTokens();\n        uber.places.getHome(function(err, res) {\n            err.message.should.equal('Invalid access token');\n            done();\n        });\n    });\n\n});\n\ndescribe('Work', function() {\n    it('should list the work address after authentication', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.places.getWork(function(err, res) {\n                    should.not.exist(err);\n                    res.should.deep.equal(reply('riders/placeWork'));\n                    done();\n                });\n            });\n    });\n\n    it('should return invalid access token error when no token found', function(done) {\n        uber.clearTokens();\n        uber.places.getWork(function(err, res) {\n            err.message.should.equal('Invalid access token');\n            done();\n        });\n    });\n});\n\ndescribe('By Place ID', function() {\n    it('should be able to update the home address', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.places.updateHome('685 Market St, San Francisco, CA 94103, USA', function(err, res) {\n                    should.not.exist(err);\n                    res.should.deep.equal(reply('riders/placeHome'));\n                    done();\n                });\n            });\n    });\n\n    it('should return error for update of home address with missing scope', function(done) {\n        uber.authorization({\n                authorization_code: acNPl\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.places.updateHome('685 Market St, San Francisco, CA 94103, USA', function(err, res) {\n                    err.message.should.equal('Required scope not found');\n                    done();\n                });\n            });\n    });\n\n    it('should be able to update the work address', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.places.updateWork('1455 Market St, San Francisco, CA 94103, USA', function(err, res) {\n                    should.not.exist(err);\n                    res.should.deep.equal(reply('riders/placeWork'));\n                    done();\n                });\n            });\n    });\n\n    it('should return error for invalid place_id for GET', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.places.getByID('shop', function(err, res) {\n                    err.message.should.equal('place_id needs to be either \"home\" or \"work\"');\n                    done();\n                });\n            });\n    });\n\n    it('should return error for missing place_id for GET', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.places.getByID(null, function(err, res) {\n                    err.message.should.equal('Invalid place_id');\n                    done();\n                });\n            });\n    });\n\n    it('should return error for invalid place_id for PUT', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.places.updateByID('shop', '685 Market St, San Francisco, CA 94103, USA', function(err, res) {\n                    err.message.should.equal('place_id needs to be either \"home\" or \"work\"');\n                    done();\n                });\n            });\n    });\n\n    it('should return error for missing place_id for PUT', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.places.updateByID(null, '685 Market St, San Francisco, CA 94103, USA', function(err, res) {\n                    err.message.should.equal('Invalid place_id');\n                    done();\n                });\n            });\n    });\n\n    it('should return error for missing new address for PUT', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.places.updateHome(null, function(err, res) {\n                    err.message.should.equal('Invalid address');\n                    done();\n                });\n            });\n    });\n});\n"
  },
  {
    "path": "test/riders/placesAsync.js",
    "content": "var common = require(\"../common\"),\n    should = common.should,\n    uber = common.uber,\n    reply = common.jsonReply,\n    ac = common.authCode,\n    acNPl = common.authCodeNoPlaces;\n\ndescribe('Home', function() {\n    it('should return error for missing access token', function(done) {\n        uber.clearTokens();\n        uber.places.updateHomeAsync('685 Market St, San Francisco, CA 94103, USA').then(function(res) {\n                should.not.exist(res);\n            })\n            .error(function(err) {\n                err.message.should.equal('Invalid access token');\n            });\n        done();\n    });\n\n    it('should list the home address after authentication', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            }).then(function(res) {\n                return uber.places.getHomeAsync();\n            })\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/placeHome'));\n            })\n            .error(function(err) {\n                should.not.exist(err);\n            });\n        done();\n    });\n\n    it('should return invalid access token error when no token found', function(done) {\n\n        uber.clearTokens();\n        uber.places.getHomeAsync().then(function(res) {\n                should.not.exist(res);\n            })\n            .error(function(err) {\n                err.message.should.equal('Invalid access token');\n            });\n        done();\n    });\n});\n\ndescribe('Work', function() {\n    it('should list the work address after authentication', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            }).then(function(access_token) {\n                return uber.places.getWorkAsync();\n            })\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/placeWork'));\n            })\n            .error(function(err) {\n                should.not.exist(err);\n            });\n        done();\n    });\n\n    it('should return invalid access token error when no token found', function(done) {\n        uber.clearTokens();\n        uber.places.getWorkAsync().then(function(res) {\n                should.not.exist(res);\n            })\n            .error(function(err) {\n                err.message.should.equal('Invalid access token');\n            });\n        done();\n    });\n});\n\ndescribe('By Place ID', function() {\n    it('should be able to update the home address', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            }).then(function(access_token) {\n                return uber.places.updateHomeAsync('685 Market St, San Francisco, CA 94103, USA');\n            })\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/placeHome'));\n            })\n            .error(function(err) {\n                should.not.exist(err);\n            });\n        done();\n    });\n\n    it('should return error for update of home address with missing scope', function(done) {\n        uber.authorizationAsync({\n                authorization_code: acNPl\n            }).then(function(access_token) {\n                return uber.places.updateHomeAsync('685 Market St, San Francisco, CA 94103, USA');\n            })\n            .error(function(err) {\n                err.message.should.equal('Required scope not found');\n            });\n        done();\n    });\n\n    it('should be able to update the work address', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            }).then(function(access_token) {\n                return uber.places.updateWorkAsync('1455 Market St, San Francisco, CA 94103, USA');\n            })\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/placeWork'));\n            })\n            .error(function(err) {\n                should.not.exist(err);\n            });\n        done();\n    });\n\n    it('should return error for invalid place_id for GET', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            }).then(function(access_token) {\n                return uber.places.getByIDAsync('shop');\n            })\n            .error(function(err) {\n                err.message.should.equal('place_id needs to be either \"home\" or \"work\"');\n            });\n        done();\n    });\n\n    it('should return error for missing place_id for GET', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            }).then(function(res) {\n                return uber.places.getByIDAsync(null);\n            })\n            .error(function(err) {\n                err.message.should.equal('Invalid place_id');\n            });\n        done();\n    });\n\n    it('should return error for invalid place_id for PUT', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            }).then(function(res) {\n                return uber.places.updateByIDAsync('shop', '685 Market St, San Francisco, CA 94103, USA');\n            })\n            .error(function(err) {\n                err.message.should.equal('place_id needs to be either \"home\" or \"work\"');\n            });\n        done();\n    });\n\n    it('should return error for missing place_id for PUT', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            }).then(function(res) {\n                return uber.places.updateByIDAsync(null, '685 Market St, San Francisco, CA 94103, USA');\n            })\n            .error(function(err) {\n                err.message.should.equal('Invalid place_id');\n            });\n        done();\n    });\n\n    it('should return error for missing new address for PUT', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            }).then(function(res) {\n                return uber.places.updateHomeAsync(null);\n            })\n            .error(function(err) {\n                err.message.should.equal('Invalid address');\n            });\n        done();\n    });\n});\n"
  },
  {
    "path": "test/riders/products.js",
    "content": "var common = require(\"../common\"),\n    should = common.should,\n    uber = common.uber,\n    uber_sandbox = common.uber_sandbox,\n    reply = common.jsonReply,\n    ac = common.authCode;\n\ndescribe('List', function() {\n    it('should list all the product types', function(done) {\n        uber.clearTokens();\n        uber.products.getAllForLocation(3.1357169, 101.6881501, function(err, res) {\n            should.not.exist(err);\n            res.should.deep.equal(reply('riders/product'));\n            done();\n        });\n    });\n\n    it('should list all the product types by address', function(done) {\n        uber.clearTokens();\n        uber.products.getAllForAddress('A', function(err, res) {\n            should.not.exist(err);\n            res.should.deep.equal(reply('riders/product'));\n            done();\n        });\n    });\n\n    it('should return error if address is empty', function(done) {\n        uber.clearTokens();\n        uber.products.getAllForAddress(' ', function(err, res) {\n            should.not.exist(res);\n            err.message.should.equal('No coordinates found for: \" \"');\n            done();\n        });\n    });\n\n    it('should return error if address is null', function(done) {\n        uber.clearTokens();\n        uber.products.getAllForAddress(null, function(err, res) {\n            should.not.exist(res);\n            err.message.should.equal('Geocoder.geocode requires a location.');\n            done();\n        });\n    });\n\n    it('should return error if there is no required params', function(done) {\n        uber.products.getAllForLocation('', null, function(err, res) {\n            err.message.should.equal('Invalid latitude & longitude');\n            done();\n        });\n    });\n});\n\ndescribe('Details', function() {\n    it('should list all the product types', function(done) {\n        uber.products.getByID('d4abaae7-f4d6-4152-91cc-77523e8165a4', function(err, res) {\n            should.not.exist(err);\n            res.should.deep.equal(reply('riders/productDetail'));\n            done();\n        });\n    });\n\n    it('should return error if there is no required params', function(done) {\n        uber.products.getByID(null, function(err, res) {\n            err.message.should.equal('Missing product_id parameter');\n            done();\n        });\n    });\n});\n\ndescribe('Set surge multiplier in Sandbox mode', function() {\n    it('should be able to set surge multiplier', function(done) {\n        uber_sandbox.products.setSurgeMultiplierByID('d4abaae7-f4d6-4152-91cc-77523e8165a4', 2.2, function(err, res) {\n            should.not.exist(err);\n            done();\n        });\n    });\n\n    it('should return error if there is no valid product_id', function(done) {\n        uber_sandbox.products.setSurgeMultiplierByID(null, 2.2, function(err, res) {\n            err.message.should.equal('Invalid product_id');\n            done();\n        });\n    });\n\n    it('should return error if there is no valid surge multiplier', function(done) {\n        uber_sandbox.products.setSurgeMultiplierByID('d4abaae7-f4d6-4152-91cc-77523e8165a4', \"2,2\", function(err, res) {\n            err.message.should.equal('Invalid surge multiplier');\n            done();\n        });\n    });\n\n    it('should return error if not in Sandbox mode', function(done) {\n        uber.products.setSurgeMultiplierByID('d4abaae7-f4d6-4152-91cc-77523e8165a4', 2.2, function(err, res) {\n            err.message.should.equal('Setting surge multiplier is only allowed in Sandbox mode');\n            done();\n        });\n    });\n});\n\ndescribe('Set driver`s availability in Sandbox mode', function() {\n    it('should be able to set driver`s availability', function(done) {\n        uber_sandbox.products.setDriversAvailabilityByID('d4abaae7-f4d6-4152-91cc-77523e8165a4', false, function(err, res) {\n            should.not.exist(err);\n            done();\n        });\n    });\n\n    it('should return error if there is no valid product_id', function(done) {\n        uber_sandbox.products.setDriversAvailabilityByID(null, false, function(err, res) {\n            err.message.should.equal('Invalid product_id');\n            done();\n        });\n    });\n\n    it('should return error if there is no valid boolean for driver`s availability', function(done) {\n        uber_sandbox.products.setDriversAvailabilityByID('d4abaae7-f4d6-4152-91cc-77523e8165a4', null, function(err, res) {\n            err.message.should.equal('Availability needs to be a boolean');\n            done();\n        });\n    });\n\n    it('should return error if not in Sandbox mode', function(done) {\n        uber.products.setDriversAvailabilityByID('d4abaae7-f4d6-4152-91cc-77523e8165a4', false, function(err, res) {\n            err.message.should.equal('Setting driver`s availability is only allowed in Sandbox mode');\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/riders/productsAsync.js",
    "content": "var common = require(\"../common\"),\n    should = common.should,\n    uber = common.uber,\n    uber_sandbox = common.uber_sandbox,\n    reply = common.jsonReply,\n    ac = common.authCode;\n\ndescribe('List', function() {\n    it('should list all the product types by address', function(done) {\n        uber.clearTokens();\n        uber.products.getAllForAddressAsync('A')\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/product'));\n                done();\n            });\n    });\n\n    it('should return error if address is empty', function(done) {\n        uber.clearTokens();\n        uber.products.getAllForAddressAsync(' ')\n            .error(function(err) {\n                err.message.should.equal('No coordinates found for: \" \"');\n                done();\n            });\n    });\n\n    it('should return error if address is null', function(done) {\n        uber.clearTokens();\n        uber.products.getAllForAddressAsync(null)\n            .error(function(err) {\n                err.message.should.equal('Geocoder.geocode requires a location.');\n                done();\n            });\n    });\n\n    it('should list all the product types', function(done) {\n        uber.clearTokens();\n        uber.products.getAllForLocationAsync(3.1357169, 101.6881501)\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/product'));\n                done();\n            });\n    });\n\n    it('should return error if there is no required params', function(done) {\n        uber.products.getAllForLocationAsync('', null)\n            .error(function(err) {\n                err.message.should.equal('Invalid latitude & longitude');\n                done();\n            });\n    });\n});\n\ndescribe('Details', function() {\n    it('should list all the product types', function(done) {\n        uber.products.getByIDAsync('d4abaae7-f4d6-4152-91cc-77523e8165a4')\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/productDetail'));\n                done();\n            });\n    });\n\n    it('should return error if there is no required params', function(done) {\n        uber.products.getByIDAsync(null)\n            .error(function(err) {\n                err.message.should.equal('Missing product_id parameter');\n                done();\n            });\n    });\n});\n\ndescribe('Set surge multiplier in Sandbox mode', function() {\n    it('should be able to set surge multiplier', function(done) {\n        uber_sandbox.products.setSurgeMultiplierByIDAsync('d4abaae7-f4d6-4152-91cc-77523e8165a4', 2.2)\n            .then(function(res) {\n                done();\n            });\n    });\n\n    it('should return error if there is no valid product_id', function(done) {\n        uber_sandbox.products.setSurgeMultiplierByIDAsync(null, 2.2)\n            .error(function(err) {\n                err.message.should.equal('Invalid product_id');\n                done();\n            });\n    });\n\n    it('should return error if there is no valid surge multiplier', function(done) {\n        uber_sandbox.products.setSurgeMultiplierByIDAsync('d4abaae7-f4d6-4152-91cc-77523e8165a4', \"2,2\")\n            .error(function(err) {\n                err.message.should.equal('Invalid surge multiplier');\n                done();\n            });\n    });\n\n    it('should return error if not in Sandbox mode', function(done) {\n        uber.products.setSurgeMultiplierByIDAsync('d4abaae7-f4d6-4152-91cc-77523e8165a4', 2.2)\n            .error(function(err) {\n                err.message.should.equal('Setting surge multiplier is only allowed in Sandbox mode');\n                done();\n            });\n    });\n});\n\ndescribe('Set driver`s availability in Sandbox mode', function() {\n    it('should be able to set driver`s availability', function(done) {\n        uber_sandbox.products.setDriversAvailabilityByIDAsync('d4abaae7-f4d6-4152-91cc-77523e8165a4', false)\n            .then(function(res) {\n                done();\n            });\n    });\n\n    it('should return error if there is no valid product_id', function(done) {\n        uber_sandbox.products.setDriversAvailabilityByIDAsync(null, false)\n            .error(function(err) {\n                err.message.should.equal('Invalid product_id');\n                done();\n            });\n    });\n\n    it('should return error if there is no valid boolean for driver`s availability', function(done) {\n        uber_sandbox.products.setDriversAvailabilityByIDAsync('d4abaae7-f4d6-4152-91cc-77523e8165a4', null)\n            .error(function(err) {\n                err.message.should.equal('Availability needs to be a boolean');\n                done();\n            });\n    });\n\n    it('should return error if not in Sandbox mode', function(done) {\n        uber.products.setDriversAvailabilityByIDAsync('d4abaae7-f4d6-4152-91cc-77523e8165a4', false)\n            .error(function(err) {\n                err.message.should.equal('Setting driver`s availability is only allowed in Sandbox mode');\n                done();\n            });\n    });\n});\n"
  },
  {
    "path": "test/riders/requests.js",
    "content": "var common = require(\"../common\"),\n    should = common.should,\n    uber = common.uber,\n    uber_sandbox = common.uber_sandbox,\n    reply = common.jsonReply,\n    ac = common.authCode,\n    acNR = common.authCodeNoRequest,\n    rPA = common.requestProductCreate,\n    rPS = common.requestProductSurge,\n    rPSOE = common.requestProductSomeOtherError;\ndescribe('Current Request', function() {\n    it('should return error for new request without authorization', function(done) {\n        uber.clearTokens();\n        uber.requests.create({\n            \"product_id\": rPA,\n            \"start_latitude\": 37.761492,\n            \"start_longitude\": -122.423941,\n            \"end_latitude\": 37.775393,\n            \"end_longitude\": -122.417546\n        }, function(err, res) {\n            err.message.should.equal('Invalid access token');\n            done();\n        });\n    });\n\n    it('should create new request after authorization', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.requests.create({\n                    \"product_id\": rPA,\n                    \"start_latitude\": 37.761492,\n                    \"start_longitude\": -122.423941,\n                    \"end_latitude\": 37.775393,\n                    \"end_longitude\": -122.417546\n                }, function(err, res) {\n                    should.not.exist(err);\n                    res.should.deep.equal(reply('riders/requestCreate'));\n                    done();\n                });\n            });\n    });\n\n    it('should create new request with address after authorization', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.requests.create({\n                    \"product_id\": rPA,\n                    \"startAddress\": 'A',\n                    \"endAddress\": 'B'\n                }, function(err, res) {\n                    should.not.exist(err);\n                    res.should.deep.equal(reply('riders/requestCreate'));\n                    done();\n                });\n            });\n    });\n\n    it('should return error for invalid start address', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.requests.create({\n                    \"product_id\": rPA,\n                    \"startAddress\": ' ',\n                    \"endAddress\": 'B'\n                }, function(err, res) {\n                    err.message.should.equal('No coordinates found for: \" \"');\n                    done();\n                });\n            });\n    });\n\n    it('should return error for invalid end address', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.requests.create({\n                    \"product_id\": rPA,\n                    \"startAddress\": 'A',\n                    \"endAddress\": ' '\n                }, function(err, res) {\n                    err.message.should.equal('No coordinates found for: \" \"');\n                    done();\n                });\n            });\n    });\n\n    it ('should return an error along with surge confirmation details if surge pricing is active', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.requests.create({\n                    \"product_id\": rPS,\n                    \"startAddress\": 'A',\n                    \"endAddress\": 'B'\n                }, function(err, res) {\n                    should.exist(err);\n                    uber.isSurge(err).should.deep.equal(true);\n                    err.surge_confirmation.should.have.property('href');\n                    err.surge_confirmation.should.have.property('surge_confirmation_id');\n                    err.surge_confirmation.should.have.property('multiplier');\n                    done();\n                });\n            });\n    });\n    it ('should create ride request after user has accepted surge pricing', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.requests.create({\n                    \"product_id\": rPS,\n                    \"startAddress\": 'A',\n                    \"endAddress\": 'B'\n                }, function(err, res) {\n                    should.exist(err);\n                    uber.isSurge(err).should.deep.equal(true);\n                    should.exist(uber.currentRequestParameters.surge_confirmation_id);\n                    uber.requests.acceptSurgeForLastRequest(function (err, res) {\n                        should.not.exist(err);\n                        res.should.deep.equal(reply('riders/requestCreate'));\n                        done();\n                    });\n                });\n            });\n    });\n    it ('should return an error if there is a blocker other than surge conflict', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.requests.create({\n                    \"product_id\": rPSOE,\n                    \"startAddress\": 'A',\n                    \"endAddress\": 'B'\n                }, function(err, res) {\n                    should.exist(err);\n                    uber.isSurge(err).should.deep.equal(false);\n                    done();\n                });\n            });\n    });\n\n    it('should return an error if there is no active surge request to accept', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.requests.acceptSurgeForLastRequest(function(err, res) {\n                    should.exist(err);\n                    done();\n                });\n            });\n    });\n\n    it('should return error if there is no required params for POST', function(done) {\n        uber.requests.create(null, function(err, res) {\n            err.message.should.equal('Invalid parameters');\n            done();\n        });\n    });\n\n    it('should return error for getting current request without authorization', function(done) {\n        uber.clearTokens();\n        uber.requests.getCurrent(function(err, res) {\n            err.message.should.equal('Invalid access token');\n            done();\n        });\n    });\n\n    it('should get current request after authorization', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.requests.getCurrent(function(err, res) {\n                    should.not.exist(err);\n                    res.should.deep.equal(reply('riders/requestAccept'));\n                    done();\n                });\n            });\n    });\n\n    it('should return error for current request with missing scope', function(done) {\n        uber.authorization({\n                authorization_code: acNR\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.requests.getCurrent(function(err, res) {\n                    err.message.should.equal('Required scope not found');\n                    done();\n                });\n            });\n    });\n\n    it('should patch current request', function(done) {\n        uber.requests.updateCurrent({}, function(err, res) {\n            should.not.exist(err);\n            done();\n        });\n    });\n\n    it('should patch current request with new end address', function(done) {\n        uber.requests.updateCurrent({\n            endAddress: 'C'\n        }, function(err, res) {\n            should.not.exist(err);\n            done();\n        });\n    });\n\n    it('should return error in case of missing parameters for patch', function(done) {\n        uber.requests.updateCurrent(null, function(err, res) {\n            err.message.should.equal('Invalid parameters');\n            done();\n        });\n    });\n\n    it('should delete current request', function(done) {\n        uber.requests.deleteCurrent(function(err, res) {\n            should.not.exist(err);\n            done();\n        });\n    });\n});\n\ndescribe('Estimate', function() {\n    it('should get estimates', function(done) {\n        uber.requests.getEstimates({\n            \"product_id\": rPA,\n            \"start_latitude\": 37.761492,\n            \"start_longitude\": -122.423941,\n            \"end_latitude\": 37.775393,\n            \"end_longitude\": -122.417546\n        }, function(err, res) {\n            should.not.exist(err);\n            res.should.deep.equal(reply('riders/requestEstimate'));\n            done();\n        });\n    });\n\n    it('should get estimates for address', function(done) {\n        uber.requests.getEstimates({\n            \"product_id\": rPA,\n            \"startAddress\": 'A',\n            \"endAddress\": 'B'\n        }, function(err, res) {\n            should.not.exist(err);\n            res.should.deep.equal(reply('riders/requestEstimate'));\n            done();\n        });\n    });\n\n    it('should return error for estimates for invalid start address', function(done) {\n        uber.requests.getEstimates({\n            \"product_id\": rPA,\n            \"startAddress\": ' ',\n            \"endAddress\": 'B'\n        }, function(err, res) {\n            err.message.should.equal('No coordinates found for: \" \"');\n            done();\n        });\n    });\n\n    it('should return error for estimates for invalid start address', function(done) {\n        uber.requests.getEstimates({\n            \"product_id\": rPA,\n            \"startAddress\": 'A',\n            \"endAddress\": ' '\n        }, function(err, res) {\n            err.message.should.equal('No coordinates found for: \" \"');\n            done();\n        });\n    });\n\n    it('should return error if there is no required params for estimates', function(done) {\n        uber.requests.getEstimates(null, function(err, res) {\n            err.message.should.equal('Invalid parameters');\n            done();\n        });\n    });\n\n});\n\ndescribe('By Request ID', function() {\n    it('should return error for getting request by ID without authorization', function(done) {\n        uber.clearTokens();\n        uber.requests.getByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', function(err, res) {\n            err.message.should.equal('Invalid access token');\n            done();\n        });\n    });\n\n    it('should get existing request by ID after authorization', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.requests.getByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', function(err, res) {\n                    should.not.exist(err);\n                    res.should.deep.equal(reply('riders/requestAccept'));\n                    done();\n                });\n            });\n    });\n\n    it('should return error in case of missing request ID', function(done) {\n        uber.requests.getByID(null, function(err, res) {\n            err.message.should.equal('Invalid request_id');\n            done();\n        });\n    });\n\n    it('should return error in case of unknown request ID', function(done) {\n        uber.requests.getByID('abcd', function(err, res) {\n            should.exist(err);\n            err.statusCode.should.equal(404);\n            done();\n        });\n    });\n\n    it('should return error for patching an existing request without authorization', function(done) {\n        uber.clearTokens();\n        uber.requests.updateByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', {}, function(err, res) {\n            err.message.should.equal('Invalid access token');\n            done();\n        });\n    });\n\n    it('should patch an existing request by ID after authorization', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.requests.updateByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', {}, function(err, res) {\n                    should.not.exist(err);\n                    done();\n                });\n            });\n    });\n\n    it('should return eroor for patch by ID with invalid start address', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.requests.updateByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', {\n                    startAddress: ' '\n                }, function(err, res) {\n                    err.message.should.equal('No coordinates found for: \" \"');\n                    done();\n                });\n            });\n    });\n\n    it('should return eroor for patch by ID with invalid end address', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.requests.updateByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', {\n                    endAddress: ' '\n                }, function(err, res) {\n                    err.message.should.equal('No coordinates found for: \" \"');\n                    done();\n                });\n            });\n    });\n\n    it('should return error in case of missing request ID for patch', function(done) {\n        uber.requests.updateByID(null, {}, function(err, res) {\n            err.message.should.equal('Invalid request_id');\n            done();\n        });\n    });\n\n    it('should return error in case of invalid request ID for patch', function(done) {\n        uber.requests.updateByID('abcd', {}, function(err, res) {\n            should.exist(err);\n            done();\n        });\n    });\n\n    it('should return error in case of missing parameters for patch', function(done) {\n        uber.requests.updateByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', null, function(err, res) {\n            err.message.should.equal('Invalid parameters');\n            done();\n        });\n    });\n\n    it('should return error for putting an existing request without authorization', function(done) {\n        uber_sandbox.clearTokens();\n        uber_sandbox.requests.setStatusByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', 'accepted', function(err, res) {\n            err.message.should.equal('Invalid access token');\n            done();\n        });\n    });\n\n    it('should return error for putting an existing request in production mode', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.requests.setStatusByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', 'accepted', function(err, res) {\n                    err.message.should.equal('PUT method for requests is only allowed in Sandbox mode');\n                    done();\n                });\n            });\n    });\n\n    it('should accept an existing request by ID after authorization', function(done) {\n        uber_sandbox.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber_sandbox.requests.setStatusByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', 'accepted', function(err, res) {\n                    should.not.exist(err);\n                    done();\n                });\n            });\n    });\n\n    it('should return error in case of missing request ID for put', function(done) {\n        uber_sandbox.requests.setStatusByID(null, 'accepted', function(err, res) {\n            err.message.should.equal('Invalid request_id');\n            done();\n        });\n    });\n\n    it('should return error in case of invalid request ID for put', function(done) {\n        uber_sandbox.requests.setStatusByID('abcd', 'accepted', function(err, res) {\n            should.exist(err);\n            done();\n        });\n    });\n\n    it('should return error in case of missing parameters for put', function(done) {\n        uber_sandbox.requests.setStatusByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', null, function(err, res) {\n            err.message.should.equal('Invalid status');\n            done();\n        });\n    });\n\n    it('should return error for deleting an existing request by ID without authorization', function(done) {\n        uber.clearTokens();\n        uber.requests.deleteByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', function(err, res) {\n            err.message.should.equal('Invalid access token');\n            done();\n        });\n    });\n\n    it('should delete an existing request by ID after authorization', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.requests.deleteByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', function(err, res) {\n                    should.not.exist(err);\n                    done();\n                });\n            });\n    });\n\n    it('should return error in case of missing request ID for delete', function(done) {\n        uber.requests.deleteByID(null, function(err, res) {\n            err.message.should.equal('Invalid request_id');\n            done();\n        });\n    });\n\n    describe('Request Details', function() {\n        it('should return error for get map without authorization', function(done) {\n            uber.clearTokens();\n            uber.requests.getMapByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', function(err, res) {\n                err.message.should.equal('Invalid access token');\n                done();\n            });\n        });\n\n        it('should get map after authorization', function(done) {\n            uber.authorization({\n                    authorization_code: ac\n                },\n                function(err, accessToken, refreshToken) {\n                    should.not.exist(err);\n                    uber.requests.getMapByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', function(err, res) {\n                        should.not.exist(err);\n                        res.should.deep.equal(reply('riders/requestMap'));\n                        done();\n                    });\n                });\n        });\n\n        it('should return error in case of missing request ID for map', function(done) {\n            uber.requests.getMapByID(null, function(err, res) {\n                err.message.should.equal('Invalid request_id');\n                done();\n            });\n        });\n\n        it('should return error for get receipt without authorization', function(done) {\n            uber.clearTokens();\n            uber.requests.getReceiptByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', function(err, res) {\n                err.message.should.equal('Invalid access token');\n                done();\n            });\n        });\n\n        it('should get receipt after authorization', function(done) {\n            uber.authorization({\n                    authorization_code: ac\n                },\n                function(err, accessToken, refreshToken) {\n                    should.not.exist(err);\n                    uber.requests.getReceiptByID('17cb78a7-b672-4d34-a288-a6c6e44d5315', function(err, res) {\n                        should.not.exist(err);\n                        res.should.deep.equal(reply('riders/requestReceipt'));\n                        done();\n                    });\n                });\n        });\n\n        it('should return error in case of missing request ID for receipt', function(done) {\n            uber.requests.getReceiptByID(null, function(err, res) {\n                err.message.should.equal('Invalid request_id');\n                done();\n            });\n        });\n    });\n});\n"
  },
  {
    "path": "test/riders/requestsAsync.js",
    "content": "var common = require(\"../common\"),\n    should = common.should,\n    uber = common.uber,\n    uber_sandbox = common.uber_sandbox,\n    reply = common.jsonReply,\n    ac = common.authCode,\n    acNR = common.authCodeNoRequest,\n    rPA = common.requestProductCreate,\n    rPS = common.requestProductSurge,\n    rPSOE = common.requestProductSomeOtherError;\n\ndescribe('Current Request', function() {\n    it('should return error for new request without authorization', function(done) {\n        uber.clearTokens();\n        uber.requests.createAsync({\n                \"product_id\": rPA,\n                \"start_latitude\": 37.761492,\n                \"start_longitude\": -122.423941,\n                \"end_latitude\": 37.775393,\n                \"end_longitude\": -122.417546\n            })\n            .error(function(err) {\n                err.message.should.equal('Invalid access token');\n                done();\n            });\n    });\n\n    it('should create new request after authorization', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            })\n            .then(function() {\n                return uber.requests.createAsync({\n                    \"product_id\": rPA,\n                    \"start_latitude\": 37.761492,\n                    \"start_longitude\": -122.423941,\n                    \"end_latitude\": 37.775393,\n                    \"end_longitude\": -122.417546\n                });\n            })\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/requestCreate'));\n                done();\n            });\n    });\n\n    it('should create new request with address after authorization', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            })\n            .then(function() {\n                return uber.requests.createAsync({\n                    \"product_id\": rPA,\n                    \"startAddress\": 'A',\n                    \"endAddress\": 'B'\n                });\n            })\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/requestCreate'));\n                done();\n            });\n    });\n\n    it('should return error for invalid start address', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            })\n            .then(function() {\n                return uber.requests.createAsync({\n                    \"product_id\": rPA,\n                    \"startAddress\": ' ',\n                    \"endAddress\": 'B'\n                });\n            })\n            .error(function(err) {\n                err.message.should.equal('No coordinates found for: \" \"');\n                done();\n            });\n    });\n\n    it('should return error for invalid start address', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            })\n            .then(function() {\n                return uber.requests.createAsync({\n                    \"product_id\": rPA,\n                    \"startAddress\": 'A',\n                    \"endAddress\": ' '\n                });\n            })\n            .error(function(err) {\n                err.message.should.equal('No coordinates found for: \" \"');\n                done();\n            });\n    });\n    it ('should return an error along with surge confirmation details if surge pricing is active', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            })\n            .then(function() {\n                return uber.requests.createAsync({\n                    \"product_id\": rPS,\n                    \"startAddress\": 'A',\n                    \"endAddress\": 'B'\n                });\n            })\n            .error(function(err) {\n                should.exist(err);\n                uber.isSurge(err).should.deep.equal(true);\n                err.surge_confirmation.should.have.property('href');\n                err.surge_confirmation.should.have.property('surge_confirmation_id');\n                err.surge_confirmation.should.have.property('multiplier');\n                done();\n            });\n    });\n    it ('should create ride request after user has accepted surge pricing', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            })\n            .then(function() {\n                return uber.requests.createAsync({\n                    \"product_id\": rPS,\n                    \"startAddress\": 'A',\n                    \"endAddress\": 'B'\n                });\n            })\n            .error(function(err) {\n                should.exist(err);\n                uber.isSurge(err).should.deep.equal(true);\n                return uber.requests.acceptSurgeForLastRequestAsync();\n            })\n            .then(function (res) {\n                should.exist(res);\n                res.should.deep.equal(reply('riders/requestCreate'));\n                done();\n            });\n    });\n    it ('should return an error if there is a blocker other than surge conflict', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            })\n            .then(function() {\n                return uber.requests.createAsync({\n                    \"product_id\": rPSOE,\n                    \"startAddress\": 'A',\n                    \"endAddress\": 'B'\n                });\n            })\n            .error(function(err) {\n                should.exist(err);\n                uber.isSurge(err).should.deep.equal(false);\n                done();\n            });\n    });\n    it('should return an error if there is no active surge request to accept', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            })\n            .then(function() {\n                return uber.requests.acceptSurgeForLastRequestAsync();\n            })\n            .error(function(err) {\n                should.exist(err);\n                done();\n            });\n    });\n    it('should return error if there is no required params for POST', function(done) {\n        uber.requests.createAsync(null)\n            .error(function(err) {\n                err.message.should.equal('Invalid parameters');\n                done();\n            });\n    });\n\n    it('should return error for getting current request without authorization', function(done) {\n        uber.clearTokens();\n        uber.requests.getCurrentAsync()\n            .error(function(err) {\n                err.message.should.equal('Invalid access token');\n                done();\n            });\n    });\n\n    it('should get current request after authorization', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            })\n            .then(function() {\n                return uber.requests.getCurrentAsync();\n            })\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/requestAccept'));\n                done();\n            });\n    });\n\n    it('should return error for current request with missing scope', function(done) {\n        uber.authorizationAsync({\n                authorization_code: acNR\n            })\n            .then(function() {\n                return uber.requests.getCurrentAsync();\n            })\n            .error(function(err) {\n                err.message.should.equal('Required scope not found');\n                done();\n            });\n    });\n\n    it('should patch current request', function(done) {\n        uber.requests.updateCurrentAsync({})\n            .then(function(res) {\n                done();\n            });\n    });\n\n    it('should patch current request with new end address', function(done) {\n        uber.requests.updateCurrentAsync({\n            endAddress: 'C'\n        }).then(function(res) {\n            done();\n        });\n    });\n\n    it('should return error in case of missing parameters for patch', function(done) {\n        uber.requests.updateCurrentAsync(null)\n            .error(function(err) {\n                err.message.should.equal('Invalid parameters');\n                done();\n            });\n    });\n\n    it('should delete current request', function(done) {\n        uber.requests.deleteCurrentAsync()\n            .then(function(res) {\n                done();\n            });\n    });\n});\n\ndescribe('Estimate', function() {\n    it('should get estimates', function(done) {\n        uber.requests.getEstimatesAsync({\n                \"product_id\": rPA,\n                \"start_latitude\": 37.761492,\n                \"start_longitude\": -122.423941,\n                \"end_latitude\": 37.775393,\n                \"end_longitude\": -122.417546\n            })\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/requestEstimate'));\n                done();\n            });\n    });\n\n    it('should get estimates for address', function(done) {\n        uber.requests.getEstimatesAsync({\n                \"product_id\": rPA,\n                \"startAddress\": 'A',\n                \"endAddress\": 'B'\n            })\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/requestEstimate'));\n                done();\n            });\n    });\n\n    it('should return error for estimates for invalid start address', function(done) {\n        uber.requests.getEstimatesAsync({\n                \"product_id\": rPA,\n                \"startAddress\": ' ',\n                \"endAddress\": 'B'\n            })\n            .error(function(err) {\n                err.message.should.equal('No coordinates found for: \" \"');\n                done();\n            });\n    });\n\n    it('should return error for estimates for invalid end address', function(done) {\n        uber.requests.getEstimatesAsync({\n                \"product_id\": rPA,\n                \"startAddress\": 'A',\n                \"endAddress\": ' '\n            })\n            .error(function(err) {\n                err.message.should.equal('No coordinates found for: \" \"');\n                done();\n            });\n    });\n\n    it('should return error if there is no required params for estimates', function(done) {\n        uber.requests.getEstimatesAsync(null)\n            .error(function(err) {\n                err.message.should.equal('Invalid parameters');\n                done();\n            });\n    });\n\n});\n\ndescribe('By Request ID', function() {\n    it('should return error for getting request by ID without authorization', function(done) {\n        uber.clearTokens();\n        uber.requests.getByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315')\n            .error(function(err) {\n                err.message.should.equal('Invalid access token');\n                done();\n            });\n    });\n\n    it('should get existing request by ID after authorization', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            })\n            .then(function() {\n                return uber.requests.getByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315');\n            })\n            .then(function(res) {\n                res.should.deep.equal(reply('riders/requestAccept'));\n                done();\n            });\n    });\n\n    it('should return error in case of missing request ID', function(done) {\n        uber.requests.getByIDAsync(null)\n            .error(function(err) {\n                err.message.should.equal('Invalid request_id');\n                done();\n            });\n    });\n\n    it('should return error in case of unknown request ID', function(done) {\n        uber.requests.getByIDAsync('abcd')\n            .error(function(err) {\n                err.statusCode.should.equal(404);\n                done();\n            });\n    });\n\n    it('should return error for patching an existing request without authorization', function(done) {\n        uber.clearTokens();\n        uber.requests.updateByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315', {})\n            .error(function(err) {\n                err.message.should.equal('Invalid access token');\n                done();\n            });\n    });\n\n    it('should patch an existing request by ID after authorization', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            })\n            .then(function() {\n                return uber.requests.updateByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315', {});\n            })\n            .then(function(res) {\n                done();\n            });\n    });\n\n    it('should return eroor for patch by ID with invalid start address', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            })\n            .then(function() {\n                return uber.requests.updateByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315', {\n                    startAddress: ' '\n                });\n            })\n            .error(function(err) {\n                err.message.should.equal('No coordinates found for: \" \"');\n                done();\n            });\n    });\n\n    it('should return eroor for patch by ID with invalid end address', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            })\n            .then(function() {\n                return uber.requests.updateByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315', {\n                    endAddress: ' '\n                });\n            })\n            .error(function(err) {\n                err.message.should.equal('No coordinates found for: \" \"');\n                done();\n            });\n    });\n\n    it('should return error in case of missing request ID for patch', function(done) {\n        uber.requests.updateByIDAsync(null, {})\n            .error(function(err) {\n                err.message.should.equal('Invalid request_id');\n                done();\n            });\n    });\n\n    it('should return error in case of invalid request ID for patch', function(done) {\n        uber.requests.updateByIDAsync('abcd', {})\n            .error(function(err) {\n                should.exist(err);\n                done();\n            });\n    });\n\n    it('should return error in case of missing parameters for patch', function(done) {\n        uber.requests.updateByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315', null)\n            .error(function(err) {\n                err.message.should.equal('Invalid parameters');\n                done();\n            });\n    });\n\n    it('should return error for putting an existing request without authorization', function(done) {\n        uber_sandbox.clearTokens();\n        uber_sandbox.requests.setStatusByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315', 'accepted')\n            .error(function(err) {\n                err.message.should.equal('Invalid access token');\n                done();\n            });\n    });\n\n    it('should return error for putting an existing request in production mode', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            })\n            .then(function() {\n                return uber.requests.setStatusByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315', 'accepted');\n            })\n            .error(function(err) {\n                err.message.should.equal('PUT method for requests is only allowed in Sandbox mode');\n                done();\n            });\n    });\n\n    it('should accept an existing request by ID after authorization', function(done) {\n        uber_sandbox.authorizationAsync({\n                authorization_code: ac\n            })\n            .then(function() {\n                return uber_sandbox.requests.setStatusByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315', 'accepted');\n            })\n            .then(function(res) {\n                done();\n            });\n    });\n\n    it('should return error in case of missing request ID for put', function(done) {\n        uber_sandbox.requests.setStatusByIDAsync(null, 'accepted')\n            .error(function(err) {\n                err.message.should.equal('Invalid request_id');\n                done();\n            });\n    });\n\n    it('should return error in case of invalid request ID for put', function(done) {\n        uber_sandbox.requests.setStatusByIDAsync('abcd', 'accepted')\n            .error(function(err) {\n                should.exist(err);\n                done();\n            });\n    });\n\n    it('should return error in case of missing parameters for put', function(done) {\n        uber_sandbox.requests.setStatusByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315', null)\n            .error(function(err) {\n                err.message.should.equal('Invalid status');\n                done();\n            });\n    });\n\n    it('should return error for deleting an existing request by ID without authorization', function(done) {\n        uber.clearTokens();\n        uber.requests.deleteByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315')\n            .error(function(err) {\n                err.message.should.equal('Invalid access token');\n                done();\n            });\n    });\n\n    it('should delete an existing request by ID after authorization', function(done) {\n        uber.authorizationAsync({\n                authorization_code: ac\n            })\n            .then(function() {\n                return uber.requests.deleteByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315');\n            })\n            .then(function(res) {\n                done();\n            });\n    });\n\n    it('should return error in case of missing request ID for delete', function(done) {\n        uber.requests.deleteByIDAsync(null)\n            .error(function(err) {\n                err.message.should.equal('Invalid request_id');\n                done();\n            });\n    });\n\n    describe('Request Details', function() {\n        it('should return error for get map without authorization', function(done) {\n            uber.clearTokens();\n            uber.requests.getMapByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315')\n                .error(function(err) {\n                    err.message.should.equal('Invalid access token');\n                    done();\n                });\n        });\n\n        it('should get map after authorization', function(done) {\n            uber.authorizationAsync({\n                    authorization_code: ac\n                })\n                .then(function() {\n                    return uber.requests.getMapByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315');\n                })\n                .then(function(res) {\n                    res.should.deep.equal(reply('riders/requestMap'));\n                    done();\n                });\n        });\n\n        it('should return error in case of missing request ID for map', function(done) {\n            uber.requests.getMapByIDAsync(null)\n                .error(function(err) {\n                    err.message.should.equal('Invalid request_id');\n                    done();\n                });\n        });\n\n        it('should return error for get receipt without authorization', function(done) {\n            uber.clearTokens();\n            uber.requests.getReceiptByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315')\n                .error(function(err) {\n                    err.message.should.equal('Invalid access token');\n                    done();\n                });\n        });\n\n        it('should get receipt after authorization', function(done) {\n            uber.authorizationAsync({\n                    authorization_code: ac\n                })\n                .then(function() {\n                    return uber.requests.getReceiptByIDAsync('17cb78a7-b672-4d34-a288-a6c6e44d5315');\n                })\n                .then(function(res) {\n                    res.should.deep.equal(reply('riders/requestReceipt'));\n                    done();\n                });\n        });\n\n        it('should return error in case of missing request ID for receipt', function(done) {\n            uber.requests.getReceiptByIDAsync(null)\n                .error(function(err) {\n                    err.message.should.equal('Invalid request_id');\n                    done();\n                });\n        });\n    });\n});\n"
  },
  {
    "path": "test/riders/user.js",
    "content": "var common = require(\"../common\"),\n    should = common.should,\n    uber = common.uber,\n    reply = common.jsonReply,\n    ac = common.authCode,\n    acNP = common.authCodeNoProfile;\n\ndescribe('Profile', function() {\n    it('should return invalid access token error when no token found', function(done) {\n        uber.clearTokens();\n        uber.user.getProfile(function(err, res) {\n            err.message.should.equal('Invalid access token');\n            done();\n        });\n    });\n\n    it('should get user profile after authentication', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.user.getProfile(function(err, res) {\n                    should.not.exist(err);\n                    res.should.deep.equal(reply('riders/profile'));\n                    done();\n                });\n            });\n    });\n\n    it('should return error for user profile with missing profile scope', function(done) {\n        uber.authorization({\n                authorization_code: acNP\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.user.getProfile(function(err, res) {\n                    err.message.should.equal('Required scope not found');\n                    done();\n                });\n            });\n    });\n\n    it('should fail apply promo code for user profile after authentication', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.user.applyPromo('already-used-code', function(err, res) {\n                    should.exist(err);\n                    done();\n                });\n            });\n    });\n\n    it('should successfully apply promo code for user profile after authentication', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.user.applyPromo('FREE_RIDEZ', function(err, res) {\n                    should.exist(res);\n                    should.not.exist(err);\n                    res.should.deep.equal(reply('riders/profilePromoSuccess'));\n                    done();\n                });\n            });\n    });\n});\n\ndescribe('History', function() {\n    it('should get user activity after authentication', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.user.getHistory(0, 5, function(err, res) {\n                    should.not.exist(err);\n                    res.should.deep.equal(reply('riders/history'));\n                    done();\n                });\n            });\n    });\n\n    it('should get user activity after authentication, even with a too high limit', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.user.getHistory(0, 99, function(err, res) {\n                    should.not.exist(err);\n                    res.should.deep.equal(reply('riders/history'));\n                    done();\n                });\n            });\n    });\n\n    it('should get user activity after authentication without required parameters', function(done) {\n        uber.authorization({\n                authorization_code: ac\n            },\n            function(err, accessToken, refreshToken) {\n                should.not.exist(err);\n                uber.user.getHistory(null, null, function(err, res) {\n                    should.not.exist(err);\n                    res.should.deep.equal(reply('riders/history'));\n                    done();\n                });\n            });\n    });\n\n    it('should return invalid access token error when no token found', function(done) {\n        uber.clearTokens();\n        uber.user.getHistory(null, null, function(err, res) {\n            err.message.should.equal('Invalid access token');\n            done();\n        });\n    });\n});\n"
  },
  {
    "path": "test/riders/userAsync.js",
    "content": "var common = require(\"../common\"),\n  should = common.should,\n  uber = common.uber,\n  reply = common.jsonReply,\n  ac = common.authCode,\n  acNP = common.authCodeNoProfile;\n\ndescribe('Profile', function() {\n  it('should return invalid access token error when no token found', function(done) {\n    uber.clearTokens();\n    uber.user.getProfileAsync().error(function(err) {\n      err.message.should.equal('Invalid access token');\n      done();\n    });\n  });\n\n  it('should get user profile after authentication', function(done) {\n    uber.authorizationAsync({authorization_code: ac}).then(function() {\n      return uber.user.getProfileAsync();\n    }).then(function(res) {\n      res.should.deep.equal(reply('riders/profile'));\n      done();\n    });\n  });\n\n  it('should return error for user profile with missing profile scope', function(done) {\n    uber.authorizationAsync({authorization_code: acNP}).then(function() {\n      return uber.user.getProfileAsync();\n    }).error(function(err) {\n      err.message.should.equal('Required scope not found');\n      done();\n    });\n  });\n\n  it('should fail apply promo code for user profile after authentication', function(done) {\n    uber.authorizationAsync({authorization_code: ac}).then(function() {\n      return uber.user.applyPromoAsync('already-used-code');\n    }).error(function(err) {\n      should.exist(err);\n      done();\n    });\n  });\n\n  it('should successfully apply promo code for user profile after authentication', function(done) {\n    uber.authorizationAsync({authorization_code: ac}).then(function() {\n      return uber.user.applyPromoAsync('FREE_RIDEZ');\n    }).then(function(res) {\n      res.should.deep.equal(reply('riders/profilePromoSuccess'));\n      done();\n    });\n  });\n});\n\ndescribe('History', function() {\n  it('should get user activity after authentication', function(done) {\n    uber.authorizationAsync({authorization_code: ac}).then(function() {\n      return uber.user.getHistoryAsync(0, 5);\n    }).then(function(res) {\n      res.should.deep.equal(reply('riders/history'));\n      done();\n    });\n  });\n\n  it('should get user activity after authentication, even with a too high limit', function(done) {\n    uber.authorizationAsync({authorization_code: ac}).then(function() {\n      return uber.user.getHistoryAsync(0, 99);\n    }).then(function(res) {\n      res.should.deep.equal(reply('riders/history'));\n      done();\n    });\n  });\n\n  it('should get user activity after authentication without required parameters', function(done) {\n    uber.authorizationAsync({authorization_code: ac}).then(function() {\n      return uber.user.getHistoryAsync(null, null);\n    }).then(function(res) {\n      res.should.deep.equal(reply('riders/history'));\n      done();\n    });\n  });\n\n  it('should return invalid access token error when no token found', function(done) {\n    uber.clearTokens();\n    uber.user.getHistoryAsync(null, null).error(function(err) {\n      err.message.should.equal('Invalid access token');\n      done();\n    });\n  });\n});\n"
  }
]