Comparing version 1.4.0 to 2.0.0-alpha
# Changelog | ||
## 2.0.0 | ||
- The promise returned from endpoints now exposes a `request` | ||
reference point to the original superagent request | ||
- Promises are not included by default. If not polyfilled, | ||
use the `Promise` option to provide the Promise implementation to | ||
use for Gangway. | ||
- `route` now operates one step shallower. See README for usage. | ||
- routes now respect relative URLs. Absolute urls will operate from the | ||
base path. | ||
### Upgrading | ||
If you are upgrading from 1.0, there are a couple of necessary | ||
changes: | ||
#### Promises | ||
If a global Promise object is not found, Gangway will throw an | ||
error. To eliminate this error, provide a Promise library to Gangway: | ||
```javascript | ||
var Promise = require('promise') | ||
Gangway({ | ||
Promise: Promise | ||
}) | ||
``` | ||
#### Routes | ||
The two-level approach to declaring routes has been removed. The | ||
following patterns should be switched out: | ||
```javascript | ||
// OLD | ||
API.route({ | ||
users: { | ||
get: { | ||
path: '/users' | ||
} | ||
} | ||
}) | ||
// NEW (correct) | ||
API.namespace('users').route{ | ||
get: { | ||
path:'/users' | ||
} | ||
}} | ||
``` | ||
#### Relative routes | ||
Routes without a `/` at the beginning will resolve to their | ||
namespace. Check to ensure that your paths are resolving correctly for | ||
your endpoints if you use absolute paths. | ||
## 1.4.0 | ||
@@ -4,0 +62,0 @@ |
@@ -22,11 +22,10 @@ # Hello Gangway | ||
Speaking of which, endpoints may be created using the `route` method: | ||
So what is an endpoint? An endpoint describes a request to an API for | ||
information. In Gangway, they are created with `route`: | ||
```javascript | ||
API.route({ | ||
users: { | ||
read: { | ||
method : 'GET', | ||
path : 'users/{id?}' | ||
} | ||
readUsers: { | ||
method : 'GET', | ||
path : 'users/{id?}' | ||
} | ||
@@ -36,24 +35,34 @@ }) | ||
Executing this code will produce namespaces on `API` for the `users` | ||
resource. This is the second layer of configuration options: the route | ||
layer. Options given to routes will override the general options | ||
specified to the API. | ||
In the code above, `route` will assign a `readUser` method to `API` | ||
that performs a GET request to `/users/{id}`. The `?` in the path | ||
indicates that the id parameter is optional. | ||
You can now perform a `GET` request to `http://example.com/users` | ||
with: | ||
### Namespaces | ||
In the previous example, we created an endpoint directly on | ||
`API`. However RESTful APIs are organized into discrete resources. In | ||
order to help you stay organized, Gangway provides a `namespace` | ||
method that will make all subsequent method calls operate within a | ||
given path: | ||
```javascript | ||
API.users.read().then(function(data) { | ||
console.log(data) | ||
var users = API.namespace('users') | ||
users.route({ | ||
read: { | ||
method : 'GET', | ||
path : '{id?} | ||
} | ||
}) | ||
``` | ||
In the code above, a request is sent out to fetch information. Gangway | ||
returns a [Promise](https://www.promisejs.org/) to represent the | ||
request. When this promise resolves, it will pass the body of the | ||
request to `.then`. | ||
This is _nearly_ the same as using `API.route`, however there are a | ||
couple of differences. First, we don't need to include `users` in the | ||
path, because the route is already working from the `users` | ||
namespace. Second, the endpoint is added at `API.users` instead of | ||
simply being available at `API`. | ||
## Individual requests | ||
The example in the previous section had a path property of | ||
The examples in the previous sections had a path property of | ||
`users/{id?}`. Gangway uses the | ||
@@ -82,5 +91,6 @@ [route pattern matching from HapiJS](http://hapijs.com/tutorials/routing) | ||
For RESTful API endpoints, manually producing a route for every action | ||
is tedious. In light of this, Gangway provides an additional | ||
`resource` method for quickly building routes for RESTful resources: | ||
`route` and `namespace` reduce a lot of boilerplate, however even this | ||
can get tedious when mapping actions for every resource of a RESTful | ||
API. To account for this, Gangway provides a `resource` method. This | ||
method helps you to quickly building endpoints for RESTful resources: | ||
@@ -94,25 +104,21 @@ ```javascript | ||
```javascript | ||
API.route({ | ||
API.namespace('users').route({ | ||
create: { | ||
method: 'POST', | ||
path: '{id}' | ||
}, | ||
users: { | ||
create: { | ||
method: 'POST', | ||
path: 'users/{id}' | ||
}, | ||
read: { | ||
method: 'GET', | ||
path: '{id?}' | ||
}, | ||
read: { | ||
method: 'GET', | ||
path: 'users/{id?}' | ||
}, | ||
update: { | ||
method: 'PATCH', | ||
path: '{id}' | ||
}, | ||
update: { | ||
method: 'PATCH', | ||
path: 'users/{id}' | ||
}, | ||
destroy: { | ||
method: 'DELETE', | ||
path: 'users/{id}' | ||
} | ||
destroy: { | ||
method: 'DELETE', | ||
path: '{id}' | ||
} | ||
@@ -119,0 +125,0 @@ }) |
@@ -5,4 +5,2 @@ # Working with Promises in Gangway | ||
2. [Promises in Gangway](#promises-in-gangway) | ||
3. [Using done() instead of then()](#using-done-instead-of-then) | ||
4. [Using nodeify for error-first callbacks](#using-nodeify-for-error-first-callbacks) | ||
@@ -18,6 +16,3 @@ ## Overview | ||
For all endpoints created by Gangway, promises are returned to | ||
represent the | ||
request. [The usage of promises is well-documented](https://www.promisejs.org/), | ||
however in Gangway we have made some decisions that build on top of | ||
promises to support a better developer experience. | ||
represent the request. | ||
@@ -29,7 +24,5 @@ The examples for this guide will assume the following setup code: | ||
API.route({ | ||
users: { | ||
read: { | ||
path: 'users/{id*} | ||
} | ||
API.namespace('users').route({ | ||
read: { | ||
path: '{id?}' | ||
} | ||
@@ -41,6 +34,2 @@ }) | ||
Gangway uses the [then/promise](https://github.com/then/promise) | ||
implementation of Promises. This means that it follows the standard, | ||
A+ Promise specification: | ||
```javascript | ||
@@ -50,4 +39,10 @@ API.users.read().then(handleSuccess, handleRejection).catch(handleError) | ||
## Using done() instead of then() | ||
Gangway does not include a Promise implementation, it is up to you to | ||
provide one. We recommended using the [then/promise](https://github.com/then/promise) | ||
implementation of Promises. | ||
Let's go into some reasons why. | ||
### Using done() instead of then() to prevent uncaught errors | ||
Promises are chainable. `then` can be called multiple times, layering | ||
@@ -58,5 +53,5 @@ on behaviors after a promise is resolved: | ||
API.users.read() | ||
.then(doSomething) | ||
.then(doSomethingElse) | ||
.catch(handleError) | ||
.then(doSomething) | ||
.then(doSomethingElse) | ||
.catch(handleError) | ||
``` | ||
@@ -105,3 +100,3 @@ | ||
## Using nodeify for error-first callbacks | ||
### Using nodeify for error-first callbacks | ||
@@ -108,0 +103,0 @@ [`then/promise`](https://github.com/then/promise) supports an |
{ | ||
"name": "gangway", | ||
"version": "1.4.0", | ||
"version": "2.0.0-alpha", | ||
"description": "A client-side API abstraction layer", | ||
@@ -22,10 +22,9 @@ "engines": { | ||
"dependencies": { | ||
"promise": "~7.1", | ||
"superagent": "~1.7" | ||
}, | ||
"devDependencies": { | ||
"faux-jax": "4.2.2", | ||
"istanbul": "0.4.2", | ||
"faux-jax": "5.0.1", | ||
"istanbul": "0.4.3", | ||
"mocha": "2.4.5" | ||
} | ||
} |
@@ -11,3 +11,3 @@ # Gangway | ||
## Usage | ||
## Getting started | ||
@@ -17,2 +17,15 @@ Gangway is a factory function that progressively layers configuration | ||
All request methods return Promises. This means you'll need to include | ||
your own polyfill for Promise (depending on your environment). We | ||
recommend [`then/promise`](https://github.com/then/promise) as it | ||
includes additional methods like `.done()` and `.nodeify()` that | ||
improve interoperability and debugging: | ||
``` | ||
require('promise/polyfill') | ||
// Continue with the rest of your code | ||
``` | ||
Alternatively, provide `Promise` as a configuration option (see below): | ||
### Create an instance of Gangway | ||
@@ -27,3 +40,4 @@ | ||
'x-api-key': 'your-token-for-every-request' | ||
} | ||
}, | ||
Promise: require('promise') // Optional, if Promise is not polyfilled | ||
}) | ||
@@ -36,4 +50,3 @@ ``` | ||
API.route({ | ||
users: { | ||
read: { | ||
getUser: { | ||
method : 'GET', | ||
@@ -46,3 +59,3 @@ path : '/users/{id?}' // ? indicates that the parameter is optional | ||
`API.users.read()` will now perform a GET request to | ||
`API.getUser()` will now perform a GET request to | ||
`/users/{id}`. The `?` in the path option specifies that it is | ||
@@ -52,2 +65,20 @@ optional. This is useful when using the same route for index and show | ||
### Add namespaces | ||
Most APIs break down endpoints into discrete resources. Gangway | ||
provides a `namespace` method for this purpose. All routes will be | ||
prefixed with a provided URL segment: | ||
```javascript | ||
API.namespace('users').route({ | ||
read: { | ||
method : 'GET', | ||
path : '{id?}' // ? indicates that the parameter is optional | ||
} | ||
} | ||
}) | ||
``` | ||
`API.users.read({ params: { id: 2 }})` will perform a GET request to `/users/2`. | ||
### Add routes in bulk with `.resource` | ||
@@ -80,2 +111,14 @@ | ||
### Accessing the original request object | ||
It is some times useful to access the unwrapped superagent request | ||
object. The value returned from endpoints contains a `request` | ||
property that grants access to this instance: | ||
```javascript | ||
let fetch = API.users.read({ params: { id: '10' } }) | ||
fetch.request.abort() | ||
``` | ||
## Documentation | ||
@@ -98,2 +141,3 @@ | ||
params : Populate bindings in paths and are sent as request bodies. Defaults to body. | ||
Promise : The Promise implementation. Defaults to global.Promise. | ||
path : The path fragment of the endpoint, appended to baseURL | ||
@@ -100,0 +144,0 @@ type : Content type, defaults to JSON |
var Mock = require('./mock') | ||
var Promise = require('promise') | ||
var Request = require('superagent') | ||
var prepare = require('./prepare') | ||
var url = require('./url') | ||
var assign = require('./assign') | ||
@@ -11,7 +9,11 @@ module.exports = function AJAX (options) { | ||
if (!options.Promise) { | ||
throw TypeError('Gangway uses Promises. The current environment does not support them. Please include a Promise polyfill.') | ||
} | ||
if ('mock' in options) { | ||
return Mock(options) | ||
return options.Promise.resolve(Mock(options)) | ||
} | ||
var location = url(options.baseURL, url.resolve(options.basePath, options.path), assign({}, options.body, options.params)) | ||
var location = url(options.baseURL, url.resolve(options.basePath, options.path), options.params) | ||
var message = Request(options.method, location) | ||
@@ -26,3 +28,3 @@ | ||
return new Promise(function(resolve, reject) { | ||
var promise = new options.Promise(function(resolve, reject) { | ||
message.end(function(err, response) { | ||
@@ -32,2 +34,6 @@ return err ? reject(options.onError(err)) : resolve(options.onResponse(response)) | ||
}) | ||
promise.request = message | ||
return promise | ||
} |
@@ -23,3 +23,3 @@ var ajax = require('./ajax') | ||
namespace: function (key) { | ||
namespace: function (key, options) { | ||
var segments = this.segments.concat(key) | ||
@@ -29,3 +29,3 @@ | ||
basePath: segmentize(segments) | ||
}) | ||
}, options) | ||
@@ -32,0 +32,0 @@ var child = Object.create(this, { |
@@ -1,7 +0,3 @@ | ||
var Promise = require('promise') | ||
module.exports = function (options) { | ||
var reply = typeof options.mock === 'function' ? options.mock(options) : options.mock | ||
return Promise.resolve(reply) | ||
return typeof options.mock === 'function' ? options.mock(options) : options.mock | ||
} |
@@ -22,3 +22,4 @@ /** | ||
onResponse : function(response) { return response.body }, | ||
onError : function(error) { return error } | ||
onError : function(error) { return error }, | ||
Promise : global.Promise | ||
} | ||
@@ -25,0 +26,0 @@ |
@@ -1,27 +0,24 @@ | ||
var assign = require('./assign') | ||
var endpoint = require('./endpoint') | ||
var route = require('./route') | ||
module.exports = function resource (API, name, options, nest) { | ||
var child = API.namespace(name) | ||
var child = API.namespace(name, options).route({ | ||
endpoint(child, { | ||
create: assign({}, options, { | ||
create: { | ||
method: 'POST' | ||
}), | ||
}, | ||
read: assign({}, options, { | ||
read: { | ||
method: 'GET', | ||
path: '{id?}' | ||
}), | ||
}, | ||
update: assign({}, options, { | ||
update: { | ||
method: 'PATCH', | ||
path: '{id}' | ||
}), | ||
}, | ||
destroy: assign({}, options, { | ||
destroy: { | ||
method: 'DELETE', | ||
path: '{id}' | ||
}) | ||
} | ||
@@ -28,0 +25,0 @@ }) |
@@ -1,6 +0,23 @@ | ||
var remap = require('./remap') | ||
var endpoint = require('./endpoint') | ||
var remap = require('./remap') | ||
var prepare = require('./prepare') | ||
var url = require('./url') | ||
module.exports = function route (API, routes) { | ||
return remap(routes || {}, endpoint.bind(null, API), API) | ||
module.exports = function route (namespace, methods) { | ||
// For each endpoint (create, read, update, delete...) | ||
return remap(methods, function (options) { | ||
var config = prepare(namespace.config, options) | ||
var request = function (overrides) { | ||
return namespace.ajax(prepare(config, overrides)) | ||
} | ||
request.toString = function () { | ||
return url.resolve(namespace.toString(), config.path) | ||
} | ||
// Make the config for this route available under 'config' | ||
request.config = config | ||
return request | ||
}, namespace) | ||
} |
@@ -5,6 +5,21 @@ var parameterizeRoute = require('./parameterizeRoute') | ||
function isAbsolute (path) { | ||
return (path || '').toString()[0] === '/' | ||
} | ||
function urlRoot (url) { | ||
return url = url.replace(/\/\w+$/, '') | ||
} | ||
function resolve (base, path) { | ||
base = (base || '').toString().replace(trimRight, '') | ||
path = (path || '').toString().replace(trimLeft, '') | ||
base = (base || '').toString() | ||
path = (path || '').toString() | ||
if (isAbsolute(path)) { | ||
base = urlRoot(base) | ||
} | ||
base = base.replace(trimRight, '') | ||
path = path.replace(trimLeft, '') | ||
return (base + '/' + path).replace(trimRight, '') | ||
@@ -18,3 +33,2 @@ } | ||
module.exports = url | ||
module.exports.resolve = resolve |
@@ -11,5 +11,7 @@ var ajax = require('../src/ajax') | ||
fauxJax.install() | ||
fauxJax.on('request', function(request) { | ||
fauxJax.on('request', function (request) { | ||
if (request.requestURL.match(/response\.json/)) { | ||
request.respond(200, { 'Content-Type': 'application/json' }, JSON.stringify({ "name" : "Gangway" })) | ||
setTimeout(function() { | ||
request.respond(200, { 'Content-Type': 'application/json' }, JSON.stringify({ "name" : "Gangway" })) | ||
}, 10) | ||
} else { | ||
@@ -29,6 +31,6 @@ request.respond(404, { 'Content-Type': 'text/plain' }, "Not found") | ||
path : '/base/test/response.json' | ||
}).done(function(body) { | ||
}).then(function(body) { | ||
assert.equal(body.name, 'Gangway') | ||
done() | ||
}) | ||
}).catch(done) | ||
}) | ||
@@ -38,4 +40,6 @@ | ||
ajax({ | ||
beforeSend(ajax) { | ||
assert.equal(ajax.header.accept, 'application/json') | ||
beforeSend: function (ajax) { | ||
// NOTE: The browser sets this header with a capital "a", however it | ||
// is lower case within Node | ||
assert.equal(ajax.header.Accept || ajax.header.accept, 'application/json') | ||
done() | ||
@@ -50,6 +54,6 @@ } | ||
mock : 'fiz' | ||
}).done(function(body) { | ||
}).then(function(body) { | ||
assert.equal(body, 'fiz') | ||
done() | ||
}) | ||
}).catch(done) | ||
}) | ||
@@ -66,6 +70,6 @@ | ||
ajax(options).done(function(data) { | ||
ajax(options).then(function(data) { | ||
assert.equal(data, 'yes') | ||
done() | ||
}) | ||
}).catch(done) | ||
}) | ||
@@ -77,6 +81,6 @@ | ||
mock : 'fiz' | ||
}).done(function(body) { | ||
}).then(function(body) { | ||
assert.equal(body, 'fiz') | ||
done() | ||
}) | ||
}).catch(done) | ||
}) | ||
@@ -88,6 +92,6 @@ | ||
path : '/asdf' | ||
}).done(null, function(error) { | ||
}).then(null, function(error) { | ||
assert.equal(error.status, 404) | ||
done() | ||
}) | ||
}).catch(done) | ||
}) | ||
@@ -99,6 +103,6 @@ | ||
path : '/base/test/response.json' | ||
}).done(function(data) { | ||
}).then(function(data) { | ||
assert.equal(data.name, 'Gangway') | ||
done() | ||
}) | ||
}).catch(done) | ||
}) | ||
@@ -111,3 +115,3 @@ | ||
params : { path: 'response'} | ||
}).nodeify(done) | ||
}).then(function () { done() }, done) | ||
}) | ||
@@ -120,3 +124,3 @@ | ||
params : { path: 'response' } | ||
}).nodeify(done) | ||
}).then(function () { done() }, done) | ||
}) | ||
@@ -128,3 +132,3 @@ | ||
path : '/base/test/response.json' | ||
}).nodeify(done) | ||
}).then(function () { done() }, done) | ||
}) | ||
@@ -139,3 +143,3 @@ | ||
} | ||
}).nodeify(done) | ||
}).then(function () { done() }, done) | ||
}) | ||
@@ -151,3 +155,3 @@ | ||
} | ||
}).nodeify(done) | ||
}).then(function () { done() }, done) | ||
}) | ||
@@ -161,4 +165,41 @@ | ||
} | ||
}).nodeify(done) | ||
}).then(function () { done() }, done) | ||
}) | ||
it ('accepts a custom Promise implimentation option', function(done) { | ||
ajax({ | ||
Promise: { | ||
resolve: function (value) { | ||
assert.equal(value, 'test') | ||
done() | ||
} | ||
}, | ||
mock: 'test' | ||
}) | ||
}) | ||
it ('throws an error when promise is not defined', function () { | ||
assert.throws(function () { | ||
return ajax({ Promise: undefined }) | ||
}, /Please include a Promise polyfill/) | ||
}) | ||
it ('can cancel requests', function (done) { | ||
var message = ajax({ | ||
baseURL : baseURL, | ||
path : '/base/test/response.json' | ||
}) | ||
function errorOut (error, callback) { | ||
done(new Error('Request should not have completed')) | ||
} | ||
message.then(errorOut, errorOut).catch(errorOut) | ||
message.request.abort() | ||
setTimeout(function() { | ||
done() | ||
}, 500) | ||
}) | ||
}) |
@@ -17,12 +17,10 @@ var API = require('../src/api') | ||
it ('maps over a list of endpoints', function() { | ||
it ('maps over a list of endpoints when instantiated', function() { | ||
var endpoints = API({ baseURL: baseURL }, { | ||
foo: { | ||
bar: { | ||
get: '/bip' | ||
} | ||
get: '/bip' | ||
} | ||
}) | ||
assert('bar' in endpoints.foo) | ||
assert('foo' in endpoints) | ||
}) | ||
@@ -34,10 +32,8 @@ | ||
endpoints.route({ | ||
foo: { | ||
bar: { | ||
get: '/bip' | ||
} | ||
bar: { | ||
get: '/bip' | ||
} | ||
}) | ||
assert('bar' in endpoints.foo) | ||
assert('bar' in endpoints) | ||
}) | ||
@@ -55,7 +51,5 @@ | ||
foo: { | ||
bar: { | ||
get: '/bip', | ||
headers: { | ||
'two': 2 | ||
} | ||
get: '/bip', | ||
headers: { | ||
'two': 2 | ||
} | ||
@@ -65,4 +59,4 @@ } | ||
assert.equal(endpoints.foo.bar.config.headers.one, 1) | ||
assert.equal(endpoints.foo.bar.config.headers.two, 2) | ||
assert.equal(endpoints.foo.config.headers.one, 1) | ||
assert.equal(endpoints.foo.config.headers.two, 2) | ||
}) | ||
@@ -80,7 +74,5 @@ | ||
foo: { | ||
bar: { | ||
get: '/bip', | ||
query: { | ||
'two': 2 | ||
} | ||
get: '/bip', | ||
query: { | ||
'two': 2 | ||
} | ||
@@ -90,4 +82,4 @@ } | ||
assert.equal(endpoints.foo.bar.config.query.one, 1) | ||
assert.equal(endpoints.foo.bar.config.query.two, 2) | ||
assert.equal(endpoints.foo.config.query.one, 1) | ||
assert.equal(endpoints.foo.config.query.two, 2) | ||
}) | ||
@@ -105,7 +97,4 @@ | ||
foo: { | ||
bar: { | ||
get: '/bip', | ||
body: { | ||
'two': 2 | ||
} | ||
body: { | ||
'two': 2 | ||
} | ||
@@ -115,4 +104,4 @@ } | ||
assert.equal(endpoints.foo.bar.config.body.one, 1) | ||
assert.equal(endpoints.foo.bar.config.body.two, 2) | ||
assert.equal(endpoints.foo.config.body.one, 1) | ||
assert.equal(endpoints.foo.config.body.two, 2) | ||
}) | ||
@@ -130,7 +119,5 @@ | ||
foo: { | ||
bar: { | ||
get: '/bip', | ||
params: { | ||
'two': 2 | ||
} | ||
get: '/bip', | ||
params: { | ||
'two': 2 | ||
} | ||
@@ -140,4 +127,4 @@ } | ||
assert.equal(endpoints.foo.bar.config.params.one, 1) | ||
assert.equal(endpoints.foo.bar.config.params.two, 2) | ||
assert.equal(endpoints.foo.config.params.one, 1) | ||
assert.equal(endpoints.foo.config.params.two, 2) | ||
}) | ||
@@ -151,7 +138,5 @@ | ||
api.route({ | ||
users: { | ||
read: { | ||
path: 'users' | ||
} | ||
api.namespace('users').route({ | ||
read: { | ||
path: '' | ||
} | ||
@@ -158,0 +143,0 @@ }) |
@@ -17,11 +17,9 @@ var API = require('../src/api') | ||
api.route({ | ||
users: { | ||
read: {} | ||
} | ||
var read = api.namespace('users').route({ | ||
read: {} | ||
}) | ||
var users = api.namespace('users') | ||
var users = api.resource('users') | ||
assert('read' in api.users) | ||
assert.equal(api.users.read, users.read, read) | ||
}) | ||
@@ -45,2 +43,30 @@ | ||
context('when a namespace is created with options', function() { | ||
var api = new API() | ||
var users = api.namespace('users', { query: { test: true }}) | ||
it ('sends those default options to child namespaces', function() { | ||
var posts = users.namespace('posts') | ||
assert.equal(posts.config.query.test, true) | ||
}) | ||
it ('sends those default options to routes', function() { | ||
var posts = users.namespace('posts').route({ | ||
create: { | ||
method: 'POST' | ||
} | ||
}) | ||
assert.equal(posts.create.config.query.test, true) | ||
}) | ||
it ('the basePath option is overrideable', function() { | ||
var posts = users.namespace('posts', { basePath: 'test' }).route({ | ||
create: { | ||
method: 'POST' | ||
} | ||
}) | ||
assert.equal(posts.create.toString(), '/test') | ||
}) | ||
}) | ||
context('when a resource is created', function() { | ||
@@ -47,0 +73,0 @@ var api = new API() |
@@ -19,9 +19,9 @@ var API = require('../src/api') | ||
route(api, { users: { read: read } }) | ||
route(api, { read: read }) | ||
it ('extends each route with configuration settings', function() { | ||
assert.equal(api.users.read.config.path, read.path) | ||
assert.equal(api.users.read.config.description, api.config.description) | ||
assert.equal(api.read.config.path, read.path) | ||
assert.equal(api.read.config.description, api.config.description) | ||
}) | ||
}) | ||
}) |
@@ -10,6 +10,2 @@ var url = require('../src/url') | ||
it ('trims path url left-handslashes', function() { | ||
assert.equal(url('http://foobar.com', '/path'), 'http://foobar.com/path') | ||
}) | ||
it ('handles both base and path urls with slashes', function() { | ||
@@ -33,2 +29,23 @@ assert.equal(url('http://foobar.com', 'path'), 'http://foobar.com/path') | ||
}) | ||
context('when resolving URL segments', function () { | ||
var samples = [ | ||
{ base: '//foobar.com', path: '/path', expected: '//foobar.com/path' }, | ||
{ base: 'http://foobar.com/fiz', path: '/path', expected: 'http://foobar.com/path' }, | ||
{ base: 'http://foobar.biz.co/fiz', path: '/path', expected: 'http://foobar.biz.co/path' }, | ||
{ base: 'http://foobar.biz.co/users', path: 'posts', expected: 'http://foobar.biz.co/users/posts' }, | ||
{ base: '/fiz', path: '/path', expected: '/path' }, | ||
{ base: '/foo', path: 'bar', expected: '/foo/bar' } | ||
] | ||
samples.forEach(function (sample) { | ||
context('for: ' + sample.base + ' + ' + sample.path, function () { | ||
it ('correctly resolves the url', function() { | ||
assert.equal(url(sample.base, sample.path), sample.expected) | ||
}) | ||
}) | ||
}) | ||
}) | ||
}) |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
48066
1
856
147
33
2
- Removedpromise@~7.1
- Removedasap@2.0.6(transitive)
- Removedpromise@7.1.1(transitive)