particle-api-js 9.4.0 → 10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,20 +15,12 @@ describe('Agent', () => {
15
15
  expect(agent.setBaseUrl.firstCall.args).to.have.lengthOf(1);
16
16
  expect(agent.setBaseUrl.firstCall.args[0]).to.eql(baseUrl);
17
17
  });
18
-
19
- it('creates a prefix function instance property from the supplied baseUrl (via setBaseUrl)', () => {
20
- const agent = new Agent();
21
- expect(agent.prefix).to.be.a('Function');
22
- // Note: validating specific .prefix function behavior seems hard without proxyquire
23
- // and this test seems sufficient
24
- // and redundant with the 'build request uses prefix if provided' test below
25
- });
26
18
  });
27
19
 
28
20
  describe('sanitize files', () => {
29
21
  it('can call sanitize will falsy value', () => {
30
22
  const agent = new Agent();
31
- expect(agent._sanitizeFiles(undefined)).to.be.falsy;
23
+ expect(agent._sanitizeFiles(undefined)).to.be.undefined;
32
24
  });
33
25
 
34
26
  it('sanitizes file names', () => {
@@ -107,25 +99,37 @@ describe('Agent', () => {
107
99
  });
108
100
 
109
101
  it('authorize no auth is unchanged', () => {
110
- expect(agent._authorizationHeader(undefined)).to.be.undefined;
111
- });
112
-
113
- it('authorize with credentials', () => {
114
- const authfn = sinon.spy();
115
- const req = { auth: authfn };
116
- const auth = { username: 'me', password: 'pwd' };
117
- expect(agent._authorizationHeader(req, auth)).to.be.equal(req);
118
- expect(authfn).to.have.been.calledWith('me', 'pwd');
102
+ expect(agent._getAuthorizationHeader(undefined)).to.eql({});
119
103
  });
120
104
 
121
105
  it('authorize with bearer', () => {
122
106
  const auth = '123';
123
107
  const bearer = 'Bearer 123';
124
- const setfn = sinon.spy();
125
- const req = { set: setfn };
126
- expect(agent._authorizationHeader(req, auth)).to.be.equal(req);
127
- expect(setfn).to.have.been.calledWith({ Authorization: bearer });
108
+ const headers = agent._getAuthorizationHeader(auth);
109
+ expect(headers).to.eql({ Authorization: bearer });
128
110
  });
111
+
112
+ if (typeof window !== 'undefined') {
113
+ it('supports auth with user/pass in browsers', () => {
114
+ const auth = {
115
+ username: 'test@particle.io',
116
+ password: 'super_secret'
117
+ };
118
+ const basic = 'Basic dGVzdEBwYXJ0aWNsZS5pbzpzdXBlcl9zZWNyZXQ=';
119
+ const headers = agent._getAuthorizationHeader(auth);
120
+ expect(headers).to.eql({ Authorization: basic });
121
+ });
122
+ } else {
123
+ it('supports auth with user/pass in node', () => {
124
+ const auth = {
125
+ username: 'test@particle.io',
126
+ password: 'super_secret'
127
+ };
128
+ const basic = 'Basic dGVzdEBwYXJ0aWNsZS5pbzpzdXBlcl9zZWNyZXQ=';
129
+ const headers = agent._getAuthorizationHeader(auth);
130
+ expect(headers).to.eql({ Authorization: basic });
131
+ });
132
+ }
129
133
  });
130
134
 
131
135
  describe('request', () => {
@@ -133,8 +137,9 @@ describe('Agent', () => {
133
137
 
134
138
  beforeEach(() => {
135
139
  agent = new Agent();
136
- agent._request = sinon.stub();
137
- agent._request.resolves('fake-response');
140
+ agent._promiseResponse = sinon.stub();
141
+ agent._promiseResponse.resolves('fake-response');
142
+ agent._buildRequest = sinon.stub();
138
143
  agent._sanitizeFiles = sinon.stub();
139
144
  });
140
145
 
@@ -148,37 +153,16 @@ describe('Agent', () => {
148
153
  .then((res) => {
149
154
  expect(res).to.be.equal('fake-response');
150
155
  expect(agent._sanitizeFiles).calledOnce.calledWith(sinon.match.same(files));
151
- expect(agent._request).calledOnce.calledWith({
152
- uri: 'abc',
153
- method: 'post',
154
- auth: undefined,
155
- headers: undefined,
156
- query: 'all',
157
- data: '123',
158
- files: sanitizedFiles,
159
- context: undefined,
160
- raw: false,
161
- form
162
- });
163
156
  });
164
157
  });
165
158
 
166
159
  it('uses default arguments for request', () => {
160
+ const args = ['abc', { args: '123' }];
161
+ agent._buildRequest.returns(args);
167
162
  return agent.request({ uri: 'abc', method:'post' })
168
163
  .then((res) => {
169
164
  expect(res).to.be.equal('fake-response');
170
- expect(agent._request).calledOnce.calledWith({
171
- uri: 'abc',
172
- method:'post',
173
- auth: undefined,
174
- headers: undefined,
175
- data: undefined,
176
- files: undefined,
177
- form: undefined,
178
- query: undefined,
179
- context: undefined,
180
- raw: false
181
- });
165
+ expect(agent._promiseResponse).calledOnce.calledWith(args);
182
166
  });
183
167
  });
184
168
 
@@ -200,7 +184,7 @@ describe('Agent', () => {
200
184
  agent._promiseResponse = sinon.stub();
201
185
  agent._promiseResponse.resolves('fake-response');
202
186
 
203
- return agent._request(options).then((res) => {
187
+ return agent.request(options).then((res) => {
204
188
  expect(res).to.be.equal('fake-response');
205
189
  expect(agent._buildRequest).calledOnce;
206
190
  expect(agent._buildRequest).calledWith(options);
@@ -209,22 +193,65 @@ describe('Agent', () => {
209
193
  });
210
194
  });
211
195
 
212
- it('builds a promise to call _sendRequest from _promiseResponse', () => {
196
+ it('builds a promise to call _promiseResponse', () => {
213
197
  const agent = new Agent();
214
198
  const req = sinon.stub();
215
- const response = 'response';
216
- const sendRequest = sinon.spy((req, fulfill) => {
217
- fulfill(response);
218
- });
219
- agent._sendRequest = sendRequest;
220
- const promise = agent._promiseResponse(req);
199
+ const response = {
200
+ ok: true,
201
+ status: 200,
202
+ json: () => Promise.resolve('response')
203
+ };
204
+ req.resolves(response);
205
+ const promise = agent._promiseResponse([], false, req);
221
206
  expect(promise).has.property('then');
222
- return promise.then((response) => {
223
- expect(sendRequest).calledOnce;
224
- // how to verify that fulfill/reject arguments are correctly passed to the promised function?
225
- //expect(sendRequest).calledWith(req, fulfill, reject);
226
- expect(response).to.be.equal('response');
207
+ return promise.then((resp) => {
208
+ expect(resp).to.be.eql({
209
+ body: 'response',
210
+ statusCode: 200
211
+ });
212
+ });
213
+ });
214
+
215
+ it('can handle error responses', () => {
216
+ const failResponseData = [
217
+ {
218
+ name: 'error text includes body error description',
219
+ response: {
220
+ status: 404,
221
+ statusText: 'file not found',
222
+ text: () => Promise.resolve('{"error_description": "file not found"}')
223
+ },
224
+ errorDescription: 'HTTP error 404 from 123.url - file not found'
225
+ },
226
+ {
227
+ name: 'error text with no body description',
228
+ response: {
229
+ status: 404,
230
+ text: () => Promise.resolve(''),
231
+ },
232
+ errorDescription: 'HTTP error 404 from 123.url'
233
+ },
234
+ {
235
+ name: 'error text with no status',
236
+ response: {},
237
+ errorDescription: 'Network error from 123.url'
238
+ }
239
+ ];
240
+ const agent = new Agent();
241
+ const req = sinon.stub();
242
+ const requests = failResponseData.map((failData) => {
243
+ const response = Object.assign({
244
+ ok: false
245
+ }, failData.response);
246
+ req.resolves(response);
247
+ const promise = agent._promiseResponse(['123.url'] , false, req);
248
+ return promise.catch((resp) => {
249
+ expect(resp.statusCode).to.eql(failData.response.status);
250
+ expect(resp.errorDescription).to.eql(failData.errorDescription);
251
+ expect(resp.shortErrorDescription).to.eql(failData.response.statusText);
252
+ });
227
253
  });
254
+ return Promise.all(requests);
228
255
  });
229
256
  });
230
257
 
@@ -232,135 +259,80 @@ describe('Agent', () => {
232
259
  let agent;
233
260
 
234
261
  beforeEach(() => {
235
- agent = new Agent();
262
+ agent = new Agent('abc');
236
263
  });
237
264
 
238
- it('uses prefix if provided', () => {
239
- agent.prefix = 'abc';
240
- const use = sinon.stub();
241
- const req = sinon.stub();
242
- req.returns({ use: use });
243
- const result = agent._buildRequest({ uri: 'uri', method: 'get', makerequest: req });
244
- expect(result).to.be.ok;
245
- expect(req).to.be.calledWith('get', 'uri');
246
- expect(use).to.be.calledWith('abc');
265
+ it('uses a baseURL if provided', () => {
266
+ const [uri] = agent._buildRequest({ uri: '/uri', method: 'get' });
267
+ expect(uri).to.equal('abc/uri');
247
268
  });
248
269
 
249
- it('does not call used if no prefix provided', () => {
250
- const use = sinon.stub();
251
- const req = sinon.stub();
252
- req.returns({ use: use });
253
- const result = agent._buildRequest({ uri: 'uri', method: 'get', makerequest: req });
254
- expect(result).to.be.ok;
255
- expect(req).to.be.calledWith('get', 'uri');
256
- expect(use).to.be.notCalled;
270
+ it('uses the provided uri if no baseURL is provided', () => {
271
+ agent.setBaseUrl(undefined);
272
+ const [uri] = agent._buildRequest({ uri: 'uri', method: 'get' });
273
+ expect(uri).to.equal('uri');
257
274
  });
258
275
 
259
- it('should invoke _applyContext with the request and context when provided', () => {
260
- agent._applyContext = sinon.stub();
261
- agent.prefix = undefined;
262
- const request = {};
263
- const context = { foo: {} };
264
- const req = sinon.stub().returns(request);
265
- agent._buildRequest({ uri: 'uri', method: 'get', context, makerequest: req });
266
- expect(agent._applyContext).to.be.calledWith(sinon.match.same(request), sinon.match.same(context));
276
+ it('generates context headers when one is provided', () => {
277
+ const context = { tool: { name: 'spanner' } };
278
+ const [, opts] = agent._buildRequest({ uri: '/uri', method: 'get', context });
279
+ expect(opts.headers).to.have.property('X-Particle-Tool', 'spanner');
267
280
  });
268
281
 
269
- it('should not invoke _applyContext when no context is provided', () => {
270
- agent._applyContext = sinon.stub();
271
- agent.prefix = undefined;
272
- const request = {};
273
- const req = sinon.stub().returns(request);
274
- agent._buildRequest({ uri: 'uri', method: 'get', makerequest: req });
275
- expect(agent._applyContext).to.not.be.called;
282
+ it('generates auth headers when an auth token is provided', () => {
283
+ const auth = 'abcd-1235';
284
+ const [, opts] = agent._buildRequest({ uri: 'uri', method: 'get', auth });
285
+ expect(opts.headers).to.have.property('Authorization', `Bearer ${auth}`);
276
286
  });
277
287
 
278
-
279
- it('should invoke authorize with the request and auth', () => {
280
- agent.prefix = undefined;
281
- const request = {};
282
- const req = sinon.stub();
283
- req.returns(request);
284
- const authorize = sinon.stub();
285
- agent._authorizationHeader = authorize;
286
- agent._buildRequest({ uri: 'uri', method: 'get', auth: '123', makerequest: req });
287
- expect(authorize).to.be.calledWith(sinon.match.same(request), '123');
288
+ it('adds new query params with the given query object', () => {
289
+ const query = { foo: 1, bar: 2 };
290
+ const [uri] = agent._buildRequest({ uri: '/uri', method: 'get', query });
291
+ expect(uri).to.equal('abc/uri?foo=1&bar=2');
288
292
  });
289
293
 
290
- it('should invoke query with the given query', () => {
291
- agent.prefix = undefined;
292
- const query = sinon.stub();
293
- const req = sinon.stub();
294
- req.returns({ query: query, authorize: sinon.stub() });
295
- agent._buildRequest({ uri: 'uri', method: 'get', query: '123', makerequest: req });
296
- expect(query).to.be.calledWith('123');
294
+ it('adds query params without colliding with existing ones', () => {
295
+ const query = { foo: 1, bar: 2 };
296
+ const [uri] = agent._buildRequest({ uri: '/uri?test=true', method: 'get', query });
297
+ expect(uri).to.equal('abc/uri?test=true&foo=1&bar=2');
297
298
  });
298
299
 
299
- it('should not query when no query given', () => {
300
- agent.prefix = undefined;
301
- const query = sinon.stub();
302
- const req = sinon.stub();
303
- req.returns({ query: query, _authorizationHeader: sinon.stub() });
304
- agent._buildRequest({ uri: 'uri', method: 'get', makerequest: req });
305
- expect(query).to.be.notCalled;
306
- });
307
-
308
- it('should invoke send when data given', () => {
309
- agent.prefix = undefined;
310
- const req = sinon.stub();
311
- const send = sinon.stub();
312
- req.returns({ send: send });
313
- agent._buildRequest({ uri: 'uri', method: 'get', data: 'abcd', makerequest: req });
314
- expect(send).to.be.calledWith('abcd');
300
+ it('adds the provided data as a JSON request body', () => {
301
+ const [, opts] = agent._buildRequest({ uri: 'uri', method: 'get', data: { a: 'abcd' } });
302
+ expect(opts.body).to.eql('{"a":"abcd"}');
303
+ expect(opts.headers).to.have.property('Content-Type', 'application/json');
315
304
  });
316
305
 
317
306
  it('should setup form send when form data is given', () => {
318
- agent.prefix = undefined;
319
- const req = sinon.stub();
320
- const send = sinon.stub();
321
- const type = sinon.stub();
322
- req.returns({ send: send, type: type });
323
- agent._buildRequest({ uri: 'uri', method: 'get', form: 'abcd', makerequest: req });
324
- expect(send).to.be.calledWith('abcd');
325
- expect(type).to.be.calledWith('form');
307
+ const [, opts] = agent._buildRequest({ uri: 'uri', method: 'get', form: { a: 'abcd' } });
308
+ expect(opts.body).to.eql('a=abcd');
326
309
  });
327
310
 
328
311
  it('should attach files', () => {
329
- agent.prefix = undefined;
330
- const req = sinon.stub();
331
- const attach = sinon.stub();
332
- req.returns({ attach: attach });
333
312
  const files = {
334
- file: { data: 'filedata', path: 'filepath' },
335
- file2: { data: 'file2data', path: 'file2path' }
313
+ file: { data: makeFile('filedata'), path: 'filepath' },
314
+ file2: { data: makeFile('file2data'), path: 'file2path' }
336
315
  };
337
- agent._buildRequest({ uri: 'uri', method: 'get', files: files, makerequest: req });
338
- expect(attach.callCount).to.be.equal(2);
339
- expect(attach).to.be.calledWith('file', 'filedata', { filepath: 'filepath' });
340
- expect(attach).to.be.calledWith('file2', 'file2data', { filepath: 'file2path' });
316
+ const [, opts] = agent._buildRequest({ uri: 'uri', method: 'get', files });
317
+ expect(opts.body.toString()).to.equal('[object FormData]');
318
+ expect(extractFilename(opts.body, 'file', 0)).to.eql('filepath');
319
+ expect(extractFilename(opts.body, 'file2', 3)).to.eql('file2path');
320
+ expect(opts.headers).to.not.have.property('Content-Type');
341
321
  });
342
322
 
343
323
  it('should attach files and form data', () => {
344
- agent.prefix = undefined;
345
- const req = sinon.stub();
346
- const attach = sinon.stub();
347
- const field = sinon.stub();
348
- req.returns({
349
- attach: attach,
350
- field: field
351
- });
352
324
  const files = {
353
- file: { data: 'filedata', path: 'filepath' },
354
- file2: { data: 'file2data', path: 'file2path' }
325
+ file: { data: makeFile('filedata'), path: 'filepath' },
326
+ file2: { data: makeFile('file2data'), path: 'file2path' }
355
327
  };
356
328
  const form = { form1: 'value1', form2: 'value2' };
357
- agent._buildRequest({ uri: 'uri', method: 'get', files: files, form: form, makerequest: req });
358
- expect(attach.callCount).to.be.equal(2);
359
- expect(attach).to.be.calledWith('file', 'filedata', { filepath: 'filepath' });
360
- expect(attach).to.be.calledWith('file2', 'file2data', { filepath: 'file2path' });
361
- expect(field.callCount).to.be.equal(2);
362
- expect(field).to.be.calledWith('form1', 'value1');
363
- expect(field).to.be.calledWith('form2', 'value2');
329
+ const [, opts] = agent._buildRequest({ uri: 'uri', method: 'get', files, form });
330
+ expect(opts.body.toString()).to.equal('[object FormData]');
331
+ expect(extractFilename(opts.body, 'file', 0)).to.eql('filepath');
332
+ expect(extractFilename(opts.body, 'file2', 3)).to.eql('file2path');
333
+ expect(extractFormName(opts.body, 'form1', 6, true)).to.eql('value1');
334
+ expect(extractFormName(opts.body, 'form2', 9, true)).to.eql('value2');
335
+ expect(opts.headers).to.not.have.property('Content-Type');
364
336
  });
365
337
 
366
338
  it('should handle nested dirs', () => {
@@ -368,9 +340,14 @@ describe('Agent', () => {
368
340
  file: { data: makeFile('filedata'), path: 'filepath.ino' },
369
341
  file2: { data: makeFile('file2data'), path: 'dir/file2path.cpp' }
370
342
  };
371
- const req = agent._buildRequest({ uri: 'uri', method: 'get', files: files });
372
- expect(extractFilename(req._formData, 'file', 0)).to.eql('filepath.ino');
373
- expect(extractFilename(req._formData, 'file2', 3)).to.eql('dir/file2path.cpp');
343
+ const [, opts] = agent._buildRequest({ uri: 'uri', method: 'get', files });
344
+ expect(extractFilename(opts.body, 'file', 0)).to.eql('filepath.ino');
345
+ expect(extractFilename(opts.body, 'file2', 3)).to.eql('dir/file2path.cpp');
346
+ });
347
+
348
+ it('sets the user agent to particle-api-js', () => {
349
+ const [, opts] = agent._buildRequest({ uri: 'uri', method: 'get' });
350
+ expect(opts.headers).to.have.property('User-Agent').that.match(/^particle-api-js/);
374
351
  });
375
352
 
376
353
  if (!inBrowser()){
@@ -378,8 +355,8 @@ describe('Agent', () => {
378
355
  const files = {
379
356
  file: { data: makeFile('filedata'), path: 'dir\\windowsfilepath.cpp' }
380
357
  };
381
- const req = agent._buildRequest({ uri: 'uri', method: 'get', files: files });
382
- expect(extractFilename(req._formData, 'file', 0)).to.eql('dir/windowsfilepath.cpp');
358
+ const [, opts] = agent._buildRequest({ uri: 'uri', method: 'get', files });
359
+ expect(extractFilename(opts.body, 'file', 0)).to.eql('dir/windowsfilepath.cpp');
383
360
  });
384
361
  }
385
362
 
@@ -402,93 +379,13 @@ describe('Agent', () => {
402
379
  return /filename="([^"]*)"/.exec(formData._streams[fieldIndex])[1];
403
380
  }
404
381
  }
405
- });
406
382
 
407
- describe('_sendRequest', () => {
408
- it('can retrieve a success response', () => {
409
- const response = { body: 'abc', statusCode:200 };
410
- const fulfill = sinon.stub();
411
- const reject = sinon.stub();
412
-
413
- const request = {
414
- end: function end(callback){
415
- callback(undefined, response);
416
- }
417
- };
418
- const end = sinon.spy(request, 'end');
419
-
420
- const agent = new Agent();
421
- const result = agent._sendRequest(request, fulfill, reject);
422
- expect(result).to.be.undefined;
423
- expect(end).to.be.calledOnce;
424
-
425
- expect(fulfill).to.be.calledOnce;
426
- // not called with response directly but with an object that is equivalent
427
- expect(fulfill).to.be.calledWith(response);
428
- expect(reject).to.not.be.called;
429
- });
430
-
431
- const failResponseData = [
432
- {
433
- name: 'error text includes body error description',
434
- response: {
435
- body: {
436
- error_description: 'file not found'
437
- }
438
- },
439
- error: { status: 404 },
440
- errorDescription: 'HTTP error 404 from 123.url - file not found'
441
- },
442
-
443
- {
444
- name: 'error text with no body description',
445
- response: { body: {} },
446
- error: { status: 404 },
447
- errorDescription: 'HTTP error 404 from 123.url'
448
- },
449
-
450
- {
451
- name: 'error text with no body',
452
- response: { },
453
- error: { status: 404 },
454
- errorDescription: 'HTTP error 404 from 123.url'
455
- },
456
-
457
- {
458
- name: 'error text with no response',
459
- error: { status: 404 },
460
- errorDescription: 'HTTP error 404 from 123.url' },
461
-
462
- {
463
- name: 'error text with no status',
464
- error: {},
465
- errorDescription: 'Network error from 123.url'
383
+ function extractFormName(formData, fieldName, fieldIndex){
384
+ if (inBrowser()){
385
+ return formData.get(fieldName);
386
+ } else {
387
+ return formData._streams[fieldIndex + 1];
466
388
  }
467
- ];
468
- for (let failData of failResponseData){
469
- it(`can retrieve an error response - ${failData.name}`, () => {
470
- const fulfill = sinon.stub();
471
- const reject = sinon.stub();
472
-
473
- const request = {
474
- url: '123.url', end: function end(callback){
475
- callback(failData.error, failData.response);
476
- }
477
- };
478
- const end = sinon.spy(request, 'end');
479
-
480
- const agent = new Agent();
481
- const result = agent._sendRequest(request, fulfill, reject);
482
- expect(result).to.be.undefined;
483
- expect(end).to.be.calledOnce;
484
- expect(fulfill).to.not.be.called;
485
- expect(reject).to.be.calledWithMatch({
486
- statusCode: failData.error.status,
487
- errorDescription: failData.errorDescription,
488
- error:failData.error,
489
- body:failData.response ? failData.response.body : undefined
490
- });
491
- });
492
389
  }
493
390
  });
494
391
 
@@ -513,57 +410,46 @@ describe('Agent', () => {
513
410
  });
514
411
  });
515
412
 
516
- describe('_applyContext', () => {
517
- let req;
518
-
519
- beforeEach(() => {
520
- req = { set: sinon.stub() };
521
- });
522
-
523
- it('applies the tool context when defined', () => {
413
+ describe('_getContextHeaders', () => {
414
+ it('generates the tool context when defined', () => {
524
415
  const context = { tool: { name: 'spanner' } };
525
- agent._applyContext(req, context);
526
- expect(req.set).to.have.been.calledOnce;
527
- expect(req.set).to.have.been.calledWith('X-Particle-Tool', 'spanner');
416
+ const subject = agent._getContextHeaders(context);
417
+ expect(subject).to.have.property('X-Particle-Tool', 'spanner');
528
418
  });
529
419
 
530
- it('does not apply the tool context when not defined',() => {
420
+ it('does not add the tool context header when not defined',() => {
531
421
  const context = { tool: { name2: 'spanner' } };
532
- agent._applyContext(req, context);
533
- expect(req.set).to.have.not.been.called;
422
+ const subject = agent._getContextHeaders(context);
423
+ expect(subject).to.not.have.property('X-Particle-Tool');
534
424
  });
535
425
 
536
- it('applies the project context when defined',() => {
426
+ it('generates the project context header when defined',() => {
537
427
  const context = { project: { name: 'blinky' } };
538
- agent._applyContext(req, context);
539
- expect(req.set).to.have.been.calledOnce;
540
- expect(req.set).to.have.been.calledWith('X-Particle-Project', 'blinky');
428
+ const subject = agent._getContextHeaders(context);
429
+ expect(subject).to.have.property('X-Particle-Project', 'blinky');
541
430
  });
542
431
 
543
- it('does not apply the tool context when not defined',() => {
432
+ it('does not generate the project context header when not defined',() => {
544
433
  const context = { project: { name2: 'blinky' } };
545
- agent._applyContext(req, context);
546
- expect(req.set).to.have.been.not.called;
434
+ const subject = agent._getContextHeaders(context);
435
+ expect(subject).to.not.have.property('X-Particle-Project');
547
436
  });
548
437
  });
549
438
 
550
- describe('_addToolContext', () => {
439
+ describe('_getToolContext', () => {
551
440
  it('does not add a header when the tool name is not defined', () => {
552
- const req = { set: sinon.stub() };
553
441
  const tool = { noname: 'cli' };
554
- agent._addToolContext(req, tool);
555
- expect(req.set).to.have.not.been.called;
442
+ const subject = agent._getToolContext(tool);
443
+ expect(subject).to.eql({});
556
444
  });
557
445
 
558
446
  it('adds a header when the tool is defined', () => {
559
- const req = { set: sinon.stub() };
560
447
  const tool = { name: 'cli' };
561
- agent._addToolContext(req, tool);
562
- expect(req.set).to.have.been.calledWith('X-Particle-Tool', 'cli');
448
+ const subject = agent._getToolContext(tool);
449
+ expect(subject).to.eql({ 'X-Particle-Tool': 'cli' });
563
450
  });
564
451
 
565
452
  it('adds a header when the tool and components is defined', () => {
566
- const req = { set: sinon.stub() };
567
453
  const tool = {
568
454
  name: 'cli',
569
455
  version: '1.2.3',
@@ -572,24 +458,22 @@ describe('Agent', () => {
572
458
  { name: 'foo', version: '0.0.1' }
573
459
  ]
574
460
  };
575
- agent._addToolContext(req, tool);
576
- expect(req.set).to.have.been.calledWith('X-Particle-Tool', 'cli@1.2.3, bar@a.b.c, foo@0.0.1');
461
+ const subject = agent._getToolContext(tool);
462
+ expect(subject).to.eql({ 'X-Particle-Tool': 'cli@1.2.3, bar@a.b.c, foo@0.0.1' });
577
463
  });
578
464
  });
579
465
 
580
466
  describe('_addProjectContext', () => {
581
467
  it('adds a header when the project is defined', () => {
582
- const req = { set: sinon.stub() };
583
468
  const project = { name: 'blinky' };
584
- agent._addProjectContext(req, project);
585
- expect(req.set).to.have.been.calledWith('X-Particle-Project', 'blinky');
469
+ const subject = agent._getProjectContext(project);
470
+ expect(subject).to.have.property('X-Particle-Project', 'blinky');
586
471
  });
587
472
 
588
473
  it('does not set the header when the project has no name', () => {
589
- const req = { set: sinon.stub() };
590
474
  const project = { noname: 'blinky' };
591
- agent._addProjectContext(req, project);
592
- expect(req.set).to.have.not.been.called;
475
+ const subject = agent._getProjectContext(project);
476
+ expect(subject).to.not.have.property('X-Particle-Project');
593
477
  });
594
478
  });
595
479
 
@@ -26,7 +26,7 @@ describe('EventStream', () => {
26
26
  it('creates an EventStream objects', () => {
27
27
  const eventStream = new EventStream('uri', 'token');
28
28
 
29
- expect(eventStream).to.be.obj;
29
+ expect(eventStream).to.own.include({ uri: 'uri', token: 'token' });
30
30
  });
31
31
  });
32
32
 
@@ -6,12 +6,12 @@ describe('Particle', () => {
6
6
  let api;
7
7
 
8
8
  beforeEach(() => {
9
- api = new Particle();
9
+ api = new Particle({ baseUrl: '' });
10
10
  });
11
11
 
12
12
  describe('downloadFile', () => {
13
13
  it('download the file', () => {
14
- const uri = 'https://s3.amazonaws.com/binaries.particle.io/libraries/neopixel/neopixel-0.0.10.tar.gz';
14
+ const uri = 'https://binaries.particle.io/libraries/neopixel/neopixel-0.0.10.tar.gz';
15
15
  const fileSize = 25505;
16
16
  return api.downloadFile({ uri })
17
17
  .then(contents => {
@@ -28,9 +28,10 @@ describe('Particle', () => {
28
28
  return api.flashTinker('deviceID', 'auth').then(() => {
29
29
  expect(api.agent._promiseResponse).to.have.been.calledOnce;
30
30
  const req = api.agent._promiseResponse.firstCall.args[0];
31
+ const options = req[1];
31
32
  expect(req).to.be.ok;
32
- expect(req.header).to.have.property('X-Particle-Tool').eql('cli@1.2.3');
33
- expect(req.header).to.have.property('X-Particle-Project').eql('blinky; version=0.0.1');
33
+ expect(options.headers).to.have.property('X-Particle-Tool').eql('cli@1.2.3');
34
+ expect(options.headers).to.have.property('X-Particle-Project').eql('blinky; version=0.0.1');
34
35
  });
35
36
  });
36
37
  });