Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/node_modules/
/build/
/.nyc_output/
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ language: node_js
node_js:
- "0.12"
- "iojs-v2"
after_success: npm run coverage
2 changes: 1 addition & 1 deletion api/request.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ function createResponseHandler(resolve, reject, info) {
var body = null;
var err = null;
if (status === 401) {
err = new errors.Unauthorized('Unauthorized', response, body);
err = new errors.Unauthorized('Unauthorized', response, data);
} else if (!(status >= 200 && status < 300)) {
err = new errors.UnexpectedResponse('Unexpected response status: ' +
status, response, data);
Expand Down
3 changes: 3 additions & 0 deletions api/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ function augmentQuadLinks(quad) {
if (links.full) {
links.full = addQueryParams(links.full, {'api_key': key});
}
if (links.thumbnail) {
links.thumbnail = addQueryParams(links.thumbnail, {'api_key': key});
}
}

return quad;
Expand Down
3 changes: 3 additions & 0 deletions cli/find-scenes.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,5 +205,8 @@ exports.description = 'Find scenes';
exports.main = main;
exports.options = options;

exports.fetch = fetch;
exports.parseAcquired = parseAcquired;
exports.parseWhere = parseWhere;
exports.resolveIntersects = resolveIntersects;
exports.resolveQuery = resolveQuery;
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"main": "api/index.js",
"scripts": {
"pretest": "eslint bin examples api cli test",
"test": "mocha --recursive test",
"test": "nyc mocha --recursive test",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"test-debug": "mocha --debug-brk --recursive test",
"start": "watchy --watch bin,examples,api,cli,test -- npm test",
"postpublish": "npm run publish-doc",
Expand All @@ -25,12 +26,14 @@
},
"devDependencies": {
"chai": "^3.0.0",
"coveralls": "^2.11.3",
"eslint": "^0.22.1",
"eslint-config-planet": "^2.0.0",
"gh-pages": "^0.3.1",
"jsdoc": "^3.3.2",
"minami": "^1.1.0",
"mocha": "^2.2.5",
"nyc": "^3.1.0",
"sinon": "^1.15.3",
"watchy": "^0.6.2"
},
Expand Down
13 changes: 11 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ To enable this every time you start a new shell, you can append the output of `p

The CLI will be fully documented when it is a bit more stable. For now, you can get a preview of what's available with this video:

[![screen shot](https://raw.githubusercontent.com/wiki/planetlabs/planet-client-js/planet-client.png)](https://vimeo.com/134018559)
[![screen shot][video-image]][video-url]

### Contributing

Expand All @@ -56,7 +56,9 @@ During development, you can start a file watcher that runs the linter and tests

npm start

[![Current Status](https://travis-ci.org/planetlabs/planet-client-js.svg?branch=master)](https://travis-ci.org/planetlabs/planet-client-js)

[![Build Status][travis-image]][travis-url]
[![Coverage Status][coveralls-image]][coveralls-url]

### License

Expand All @@ -65,3 +67,10 @@ During development, you can start a file watcher that runs the linter and tests
Licensed under the [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) (the "License"); you may not use this file except in compliance with the License.

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See [the License](http://www.apache.org/licenses/LICENSE-2.0) for the specific language governing permissions and limitations under the License.

[video-url]: https://vimeo.com/134018559
[video-image]: https://raw.githubusercontent.com/wiki/planetlabs/planet-client-js/planet-client.png
[travis-url]: https://travis-ci.org/planetlabs/planet-client-js
[travis-image]: https://img.shields.io/travis/planetlabs/planet-client-js.svg
[coveralls-url]: https://coveralls.io/github/planetlabs/planet-client-js
[coveralls-image]: https://img.shields.io/coveralls/planetlabs/planet-client-js.svg
13 changes: 12 additions & 1 deletion test/api/auth-store.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ var assert = require('chai').assert;

var authStore = require('../../api/auth-store');

describe('authStore', function() {
describe('api/auth-store', function() {
afterEach(function() {
authStore.clear();
});
Expand All @@ -23,6 +23,17 @@ describe('authStore', function() {
assert.equal(authStore.getKey(), 'my-api-key');
});

it('throws if the token does not contain an api_key claim', function() {
// {foo: 'bar'}
var bogus = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJmb28iOiJiYXIifQ.' +
'yPmf5QFV26W-3ldVCrsvRdnecy7QjA0fnCWCDLDZ-M4';

function call() {
authStore.setToken(bogus);
}
assert.throws(call, Error, 'Expected api_key in token payload');
});

});

describe('getToken()', function() {
Expand Down
53 changes: 48 additions & 5 deletions test/api/auth.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ var sinon = require('sinon');

var auth = require('../../api/auth');
var authStore = require('../../api/auth-store');
var errors = require('../../api/errors');

describe('auth', function() {
describe('api/auth', function() {

var httpRequest = http.request;
var httpsRequest = https.request;
Expand Down Expand Up @@ -39,9 +40,6 @@ describe('auth', function() {
https.request = httpsRequest;
mockRequest = null;
authStore.clear();
});

afterEach(function() {
auth.logout();
});

Expand Down Expand Up @@ -78,7 +76,30 @@ describe('auth', function() {
assert.equal(authStore.getToken(), token);
assert.equal(authStore.getKey(), 'my-api-key');
done();
}, done);
}).catch(done);

assert.equal(https.request.callCount, 1);
var args = https.request.getCall(0).args;
assert.lengthOf(args, 2);
var callback = args[1];
callback(response);
response.emit('data', JSON.stringify(body));
response.emit('end');
});

it('rejects if body does not contain a token', function(done) {
var response = new stream.Readable();
response.statusCode = 200;
var body = {foo: 'bar'};

var email = 'user@email.com';
var password = 'psswd';
auth.login(email, password).then(function(success) {
done(new Error('Expected rejection'));
}, function(err) {
assert.instanceOf(err, errors.UnexpectedResponse);
done();
}).catch(done);

assert.equal(https.request.callCount, 1);
var args = https.request.getCall(0).args;
Expand All @@ -89,6 +110,28 @@ describe('auth', function() {
response.emit('end');
});

it('rejects if body contains a bogus token', function(done) {
var response = new stream.Readable();
response.statusCode = 200;
var body = {token: 'bogus'};

var email = 'user@email.com';
var password = 'psswd';
auth.login(email, password).then(function(success) {
done(new Error('Expected rejection'));
}, function(err) {
assert.instanceOf(err, errors.UnexpectedResponse);
done();
}).catch(done);

assert.equal(https.request.callCount, 1);
var args = https.request.getCall(0).args;
assert.lengthOf(args, 2);
var callback = args[1];
callback(response);
response.emit('data', JSON.stringify(body));
response.emit('end');
});
});

describe('setKey()', function() {
Expand Down
2 changes: 1 addition & 1 deletion test/api/errors.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ var assert = require('chai').assert;

var errors = require('../../api/errors');

describe('errors', function() {
describe('api/errors', function() {

describe('ResponseError', function() {
it('is a generic response error', function() {
Expand Down
185 changes: 185 additions & 0 deletions test/api/mosaics.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
/* eslint-env mocha */

var assert = require('chai').assert;

var Page = require('../../api/page');
var auth = require('../../api/auth');
var request = require('../../api/request');
var mosaics = require('../../api/mosaics');
var urls = require('../../api/urls');
var util = require('../../api/util');

describe('api/mosaics', function() {

var mosaic;
beforeEach(function() {
mosaic = util.assign({}, {
name: 'one',
links: {
quads: 'https://example.com/mosaics/one/quads/',
self: 'https://example.com/mosaics/one',
tiles: 'https://s{0-3}.example.com/v0/mosaics/one/{z}/{x}/{y}.png',
quadmap: 'https://example.com/mosaics/one/quad-map.png'
},
'first_acquired': '2014-03-20T15:57:11+00:00',
datatype: 'byte',
'quad_size': 4096,
title: 'A Mosaic',
'coordinate_system': 'EPSG:3857',
geometry: {
type: 'Polygon',
coordinates: [
[[-180, -90], [-180, 90], [180, 90], [180, -90], [-180, -90]]
]
},
'last_acquired': '2015-07-20T02:11:31.947579+00:00',
'scene_type': 'ortho',
'quad_pattern': 'L{glevel:d}-{tilex:04d}E-{tiley:04d}N',
level: 15,
resolution: 4.77731426716
});
});

var get = request.get;
afterEach(function() {
request.get = get;
auth.logout();
});

describe('get()', function() {

it('requests a mosiac by id', function(done) {
var calls = [];

request.get = function(config) {
calls.push(config);
return Promise.resolve({
body: mosaic
});
};

var promise = mosaics.get('one');
assert.lengthOf(calls, 1);
var arg = calls[0];
assert.equal(arg.url, urls.join(urls.MOSAICS, 'one'));

promise.then(function(got) {
assert.deepEqual(got, mosaic);
done();
}).catch(done);
});

it('augments links if key is set', function(done) {
auth.setKey('my-key');

request.get = function(config) {
return Promise.resolve({
body: mosaic
});
};

var promise = mosaics.get('one');

promise.then(function(got) {
assert.equal(got.links.tiles,
'https://s{0-3}.example.com/v0/mosaics/one/{z}/{x}/{y}.png' +
'?api_key=my-key');
done();
}).catch(done);
});

it('can be told not to augment links', function(done) {
auth.setKey('my-key');

request.get = function(config) {
return Promise.resolve({
body: mosaic
});
};

var promise = mosaics.get('one', {augmentLinks: false});

promise.then(function(got) {
assert.equal(got.links.tiles,
'https://s{0-3}.example.com/v0/mosaics/one/{z}/{x}/{y}.png');
done();
}).catch(done);
});

});

describe('search()', function() {

it('queries the mosaics collection', function(done) {
var calls = [];

request.get = function(config) {
calls.push(config);
return Promise.resolve({
body: {
mosaics: [mosaic],
links: {}
}
});
};

var query = {
count: 1
};

var promise = mosaics.search(query);

var arg = calls[0];
assert.equal(arg.url, urls.MOSAICS);
assert.deepEqual(arg.query, query);

promise.then(function(got) {
assert.instanceOf(got, Page);
assert.lengthOf(got.data.mosaics, 1);
assert.deepEqual(got.data.mosaics[0], mosaic);
done();
}).catch(done);
});

it('augments links if key is set', function(done) {
auth.setKey('my-key');

request.get = function(config) {
return Promise.resolve({
body: {
mosaics: [mosaic],
links: {}
}
});
};

mosaics.search({}).then(function(got) {
assert.equal(got.data.mosaics[0].links.tiles,
'https://s{0-3}.example.com/v0/mosaics/one/{z}/{x}/{y}.png?' +
'api_key=my-key');
done();
}).catch(done);
});

it('can be told not to augment links', function(done) {
auth.setKey('my-key');

request.get = function(config) {
return Promise.resolve({
body: {
mosaics: [mosaic],
links: {}
}
});
};

mosaics.search({}, {augmentLinks: false}).then(function(got) {
assert.equal(got.data.mosaics[0].links.tiles,
'https://s{0-3}.example.com/v0/mosaics/one/{z}/{x}/{y}.png');
done();
}).catch(done);
});

});

});
Loading