spec(nylas-api): Update tests to use NylasAPIRequest

This commit is contained in:
Jackie Luo 2016-11-29 16:40:53 -08:00
commit 96c4a4cb5d
15 changed files with 175 additions and 159 deletions

View file

@ -2,6 +2,7 @@ _ = require 'underscore'
fs = require 'fs'
Actions = require('../src/flux/actions').default
NylasAPI = require '../src/flux/nylas-api'
NylasAPIRequest = require '../src/flux/nylas-api-request'
Thread = require('../src/flux/models/thread').default
Message = require('../src/flux/models/message').default
AccountStore = require '../src/flux/stores/account-store'
@ -18,7 +19,7 @@ describe "NylasAPI", ->
@resolved = false
spyOn(NylasEnv.config, 'set')
spyOn(NylasEnv.config, 'get').andReturn(null)
spyOn(NylasAPI, 'makeRequest').andCallFake (options) =>
spyOn(NylasAPIRequest.prototype, 'run').andCallFake (options) =>
return @authGetResponse if options.method is 'GET' and @authGetResponse
return @authPostResponse if options.method is 'POST' and @authPostResponse
return new Promise (resolve, reject) -> #never respond
@ -47,14 +48,14 @@ describe "NylasAPI", ->
@resolved = true
waitsFor =>
@resolved
expect(NylasAPI.makeRequest).not.toHaveBeenCalled()
expect(NylasAPIRequest.prototype.run).not.toHaveBeenCalled()
describe "check for existing auth", ->
it "should GET /auth/plugin to check if the plugin has been authed", ->
@authGetResponse = Promise.resolve({authed: true})
NylasAPI.authPlugin('PID', 'PSECRET', TEST_ACCOUNT_ID)
advanceClock()
expect(NylasAPI.makeRequest).toHaveBeenCalledWith({
expect(NylasAPIRequest.run).toHaveBeenCalledWith({
returnsModel: false,
method: 'GET',
accountId: 'test-account-server-id',
@ -68,7 +69,7 @@ describe "NylasAPI", ->
waitsFor =>
@resolved
runs =>
expect(NylasAPI.makeRequest).toHaveBeenCalled()
expect(NylasAPIRequest.prototype.run).toHaveBeenCalled()
expect(NylasEnv.config.set.mostRecentCall.args[0]).toEqual("plugins.PID.lastAuth.#{TEST_ACCOUNT_ID}")
it "should propagate any network errors back to the caller", ->
@ -87,13 +88,13 @@ describe "NylasAPI", ->
waitsFor =>
@resolved
runs =>
expect(NylasAPI.makeRequest.calls[0].args[0]).toEqual({
expect(NylasAPIRequest.prototype.run.calls[0].args[0]).toEqual({
returnsModel: false,
method: 'GET',
accountId: 'test-account-server-id',
path: '/auth/plugin?client_id=PID'
})
expect(NylasAPI.makeRequest.calls[1].args[0]).toEqual({
expect(NylasAPIRequest.prototype.run.calls[1].args[0]).toEqual({
returnsModel: false,
method: 'POST',
accountId: 'test-account-server-id',
@ -119,7 +120,7 @@ describe "NylasAPI", ->
spyOn(DatabaseTransaction.prototype, 'unpersistModel')
spyOn(DatabaseStore, 'find').andCallFake (klass, id) =>
return Promise.resolve(model)
NylasAPI._handleModel404("/threads/#{model.id}")
NylasAPI.handleModel404("/threads/#{model.id}")
advanceClock()
expect(DatabaseStore.find).toHaveBeenCalledWith(Thread, model.id)
expect(DatabaseTransaction.prototype.unpersistModel).toHaveBeenCalledWith(model)
@ -128,7 +129,7 @@ describe "NylasAPI", ->
spyOn(DatabaseTransaction.prototype, 'unpersistModel')
spyOn(DatabaseStore, 'find').andCallFake (klass, id) =>
return Promise.resolve(null)
NylasAPI._handleModel404("/threads/1234")
NylasAPI.handleModel404("/threads/1234")
advanceClock()
expect(DatabaseStore.find).toHaveBeenCalledWith(Thread, '1234')
expect(DatabaseTransaction.prototype.unpersistModel).not.toHaveBeenCalledWith()
@ -137,7 +138,7 @@ describe "NylasAPI", ->
spyOn(DatabaseStore, 'find')
spyOn(DatabaseTransaction.prototype, 'unpersistModel')
waitsForPromise ->
NylasAPI._handleModel404("/asdasdasd/1234")
NylasAPI.handleModel404("/asdasdasd/1234")
runs ->
expect(DatabaseStore.find).not.toHaveBeenCalled()
expect(DatabaseTransaction.prototype.unpersistModel).not.toHaveBeenCalled()
@ -146,7 +147,7 @@ describe "NylasAPI", ->
spyOn(DatabaseStore, 'find')
spyOn(DatabaseTransaction.prototype, 'unpersistModel')
waitsForPromise ->
NylasAPI._handleModel404("/account")
NylasAPI.handleModel404("/account")
runs ->
expect(DatabaseStore.find).not.toHaveBeenCalled()
expect(DatabaseTransaction.prototype.unpersistModel).not.toHaveBeenCalled()
@ -155,13 +156,13 @@ describe "NylasAPI", ->
it "should put the account in an `invalid` state", ->
spyOn(Actions, 'updateAccount')
spyOn(AccountStore, 'tokenForAccountId').andReturn('token')
NylasAPI._handleAuthenticationFailure('/threads/1234', 'token')
NylasAPI.handleAuthenticationFailure('/threads/1234', 'token')
expect(Actions.updateAccount).toHaveBeenCalled()
expect(Actions.updateAccount.mostRecentCall.args).toEqual([AccountStore.accounts()[0].id, {syncState: 'invalid'}])
it "should not throw an exception if the account cannot be found", ->
spyOn(Actions, 'updateAccount')
NylasAPI._handleAuthenticationFailure('/threads/1234', 'token')
NylasAPI.handleAuthenticationFailure('/threads/1234', 'token')
expect(Actions.updateAccount).not.toHaveBeenCalled()
describe "handleModelResponse", ->
@ -338,11 +339,11 @@ describe "NylasAPI", ->
describe "makeDraftDeletionRequest", ->
it "should make an API request to delete the draft", ->
draft = new Message(accountId: TEST_ACCOUNT_ID, draft: true, clientId: 'asd', serverId: 'asd')
spyOn(NylasAPI, 'makeRequest')
spyOn(NylasAPIRequest.prototype, 'run')
NylasAPI.makeDraftDeletionRequest(draft)
expect(NylasAPI.makeRequest).toHaveBeenCalled()
expect(NylasAPI.makeRequest.callCount).toBe 1
req = NylasAPI.makeRequest.calls[0].args[0]
expect(NylasAPIRequest.prototype.run).toHaveBeenCalled()
expect(NylasAPIRequest.prototype.run.callCount).toBe 1
req = NylasAPIRequest.prototype.run.calls[0].args[0]
expect(req.path).toBe "/drafts/#{draft.serverId}"
expect(req.accountId).toBe TEST_ACCOUNT_ID
expect(req.method).toBe "DELETE"
@ -361,6 +362,6 @@ describe "NylasAPI", ->
it "should not do anything if the draft is missing a serverId", ->
draft = new Message(accountId: TEST_ACCOUNT_ID, draft: true, clientId: 'asd', serverId: null)
spyOn(NylasAPI, 'makeRequest')
spyOn(NylasAPIRequest.prototype, 'run')
NylasAPI.makeDraftDeletionRequest(draft)
expect(NylasAPI.makeRequest).not.toHaveBeenCalled()
expect(NylasAPIRequest.prototype.run).not.toHaveBeenCalled()

View file

@ -1,6 +1,7 @@
_ = require 'underscore'
keytar = require 'keytar'
NylasAPI = require '../../src/flux/nylas-api'
NylasAPIRequest = require '../../src/flux/nylas-api-request'
AccountStore = require '../../src/flux/stores/account-store'
Account = require('../../src/flux/models/account').default
Actions = require('../../src/flux/actions').default
@ -167,7 +168,7 @@ describe "AccountStore", ->
describe "refreshHealthOfAccounts", ->
beforeEach ->
@spyOnConfig()
spyOn(NylasAPI, 'makeRequest').andCallFake (options) =>
spyOn(NylasAPIRequest.prototype, 'run').andCallFake (options) =>
if options.accountId is 'return-api-error'
Promise.reject(new Error("API ERROR"))
else
@ -181,9 +182,9 @@ describe "AccountStore", ->
it "should GET /account for each of the provided account IDs", ->
@instance.refreshHealthOfAccounts(['A', 'B'])
expect(NylasAPI.makeRequest.callCount).toBe(2)
expect(NylasAPI.makeRequest.calls[0].args).toEqual([{path: '/account', accountId: 'A'}])
expect(NylasAPI.makeRequest.calls[1].args).toEqual([{path: '/account', accountId: 'B'}])
expect(NylasAPIRequest.prototype.run.callCount).toBe(2)
expect(NylasAPIRequest.prototype.run.calls[0].args).toEqual([{path: '/account', accountId: 'A'}])
expect(NylasAPIRequest.prototype.run.calls[1].args).toEqual([{path: '/account', accountId: 'B'}])
it "should update existing account objects and call save exactly once", ->
@instance.accountForId('A').syncState = 'invalid'

View file

@ -3,6 +3,7 @@ Rx = require 'rx-lite'
{NylasTestUtils} = require 'nylas-exports'
Contact = require('../../src/flux/models/contact').default
NylasAPI = require '../../src/flux/nylas-api'
NylasAPIRequest = require '../../src/flux/nylas-api-request'
ContactStore = require '../../src/flux/stores/contact-store'
ContactRankingStore = require '../../src/flux/stores/contact-ranking-store'
DatabaseStore = require('../../src/flux/stores/database-store').default
@ -20,7 +21,7 @@ describe "ContactStore", ->
["evanC@nylas.com", 0.1]
]
spyOn(NylasAPI, "makeRequest").andCallFake (options) =>
spyOn(NylasAPIRequest.prototype, "run").andCallFake (options) =>
if options.path is "/contacts/rankings"
return Promise.resolve(@rankings)
else

View file

@ -2,6 +2,7 @@ fs = require 'fs'
path = require 'path'
{shell} = require 'electron'
NylasAPI = require '../../src/flux/nylas-api'
NylasAPIRequest = require '../../src/flux/nylas-api-request'
File = require('../../src/flux/models/file').default
Message = require('../../src/flux/models/message').default
FileDownloadStore = require('../../src/flux/stores/file-download-store').default
@ -14,7 +15,7 @@ describe 'FileDownloadStoreSpecs', ->
describe "Download", ->
beforeEach ->
spyOn(fs, 'createWriteStream')
spyOn(NylasAPI, 'makeRequest')
spyOn(NylasAPIRequest.prototype, 'run')
describe "constructor", ->
it "should require a non-empty filename", ->
@ -35,14 +36,14 @@ describe 'FileDownloadStoreSpecs', ->
account = AccountStore.accounts()[0]
@download = new Download(fileId: '123', targetPath: 'test.png', filename: 'test.png', accountId: account.id)
@download.run()
expect(NylasAPI.makeRequest).toHaveBeenCalled()
expect(NylasAPIRequest.prototype.run).toHaveBeenCalled()
it "should create a request with a null encoding to prevent the request library from attempting to parse the (potentially very large) response", ->
expect(NylasAPI.makeRequest.mostRecentCall.args[0].json).toBe(false)
expect(NylasAPI.makeRequest.mostRecentCall.args[0].encoding).toBe(null)
expect(NylasAPIRequest.prototype.run.mostRecentCall.args[0].json).toBe(false)
expect(NylasAPIRequest.prototype.run.mostRecentCall.args[0].encoding).toBe(null)
it "should create a request for /files/123/download", ->
expect(NylasAPI.makeRequest.mostRecentCall.args[0].path).toBe("/files/123/download")
expect(NylasAPIRequest.prototype.run.mostRecentCall.args[0].path).toBe("/files/123/download")
describe "FileDownloadStore", ->
beforeEach ->

View file

@ -4,8 +4,9 @@ _ = require 'underscore'
Folder,
Thread,
Message,
ACtions,
Actions,
NylasAPI,
NylasAPIRequest,
Query,
DatabaseStore,
DatabaseTransaction,
@ -269,19 +270,19 @@ describe "ChangeMailTask", ->
if model is @threadAMesage1
return {field: 'message-1'}
it "should call NylasAPI.makeRequest for each model, passing the result of requestBodyForModel", ->
spyOn(NylasAPI, 'makeRequest').andReturn(Promise.resolve())
it "should call NylasAPIRequest.run for each model, passing the result of requestBodyForModel", ->
spyOn(NylasAPIRequest.prototype, 'run').andReturn(Promise.resolve())
runs ->
@task._performRequests(Thread, [@threadA, @threadB])
waitsFor ->
NylasAPI.makeRequest.callCount is 2
NylasAPIRequest.prototype.run.callCount is 2
runs ->
expect(NylasAPI.makeRequest.calls[0].args[0].body).toEqual({field: 'thread-a-body'})
expect(NylasAPI.makeRequest.calls[1].args[0].body).toEqual({field: 'thread-b-body'})
expect(NylasAPIRequest.prototype.run.calls[0].args[0].body).toEqual({field: 'thread-a-body'})
expect(NylasAPIRequest.prototype.run.calls[1].args[0].body).toEqual({field: 'thread-b-body'})
it "should resolve when all of the requests complete", ->
promises = []
spyOn(NylasAPI, 'makeRequest').andCallFake ->
spyOn(NylasAPIRequest.prototype, 'run').andCallFake ->
new Promise (resolve, reject) -> promises.push({resolve, reject})
resolved = false
@ -289,7 +290,7 @@ describe "ChangeMailTask", ->
@task._performRequests(Thread, [@threadA, @threadB]).then =>
resolved = true
waitsFor ->
NylasAPI.makeRequest.callCount is 2
NylasAPIRequest.prototype.run.callCount is 2
runs ->
expect(resolved).toBe(false)
promises[0].resolve()
@ -301,7 +302,7 @@ describe "ChangeMailTask", ->
it "should carry on and resolve if a request 404s, since the NylasAPI manager will clean the object from the cache", ->
promises = []
spyOn(NylasAPI, 'makeRequest').andCallFake ->
spyOn(NylasAPIRequest.prototype, 'run').andCallFake ->
new Promise (resolve, reject) -> promises.push({resolve, reject})
resolved = false
@ -309,7 +310,7 @@ describe "ChangeMailTask", ->
@task._performRequests(Thread, [@threadA, @threadB]).then =>
resolved = true
waitsFor ->
NylasAPI.makeRequest.callCount is 2
NylasAPIRequest.prototype.run.callCount is 2
runs ->
promises[0].resolve()
promises[1].reject(new APIError(statusCode: 404))
@ -318,7 +319,7 @@ describe "ChangeMailTask", ->
it "should reject with the request error encountered by any request", ->
promises = []
spyOn(NylasAPI, 'makeRequest').andCallFake ->
spyOn(NylasAPIRequest.prototype, 'run').andCallFake ->
new Promise (resolve, reject) -> promises.push({resolve, reject})
err = null
@ -326,7 +327,7 @@ describe "ChangeMailTask", ->
@task._performRequests(Thread, [@threadA, @threadB]).catch (error) =>
err = error
waitsFor ->
NylasAPI.makeRequest.callCount is 2
NylasAPIRequest.prototype.run.callCount is 2
runs ->
expect(err).toBe(null)
promises[0].resolve()
@ -338,45 +339,45 @@ describe "ChangeMailTask", ->
expect(err).toBe(apiError)
it "should use /threads when the klass provided is Thread", ->
spyOn(NylasAPI, 'makeRequest').andCallFake ->
spyOn(NylasAPIRequest.prototype, 'run').andCallFake ->
new Promise (resolve, reject) -> #noop
runs ->
@task._performRequests(Thread, [@threadA, @threadB])
waitsFor ->
NylasAPI.makeRequest.callCount is 2
NylasAPIRequest.prototype.run.callCount is 2
runs ->
path = "/threads/#{@threadA.id}"
expect(NylasAPI.makeRequest.calls[0].args[0].path).toBe(path)
expect(NylasAPI.makeRequest.calls[0].args[0].accountId).toBe(@threadA.accountId)
expect(NylasAPIRequest.prototype.run.calls[0].args[0].path).toBe(path)
expect(NylasAPIRequest.prototype.run.calls[0].args[0].accountId).toBe(@threadA.accountId)
it "should use /messages when the klass provided is Message", ->
spyOn(NylasAPI, 'makeRequest').andCallFake ->
spyOn(NylasAPIRequest.prototype, 'run').andCallFake ->
new Promise (resolve, reject) -> #noop
runs ->
@task._performRequests(Message, [@threadAMesage1])
waitsFor ->
NylasAPI.makeRequest.callCount is 1
NylasAPIRequest.prototype.run.callCount is 1
runs ->
path = "/messages/#{@threadAMesage1.id}"
expect(NylasAPI.makeRequest.calls[0].args[0].path).toBe(path)
expect(NylasAPI.makeRequest.calls[0].args[0].accountId).toBe(@threadAMesage1.accountId)
expect(NylasAPIRequest.prototype.run.calls[0].args[0].path).toBe(path)
expect(NylasAPIRequest.prototype.run.calls[0].args[0].accountId).toBe(@threadAMesage1.accountId)
it "should decrement change counts as requests complete", ->
spyOn(NylasAPI, 'makeRequest').andCallFake ->
spyOn(NylasAPIRequest.prototype, 'run').andCallFake ->
new Promise (resolve, reject) -> #noop
spyOn(@task, '_removeLock')
runs ->
@task._performRequests(Thread, [@threadAMesage1])
waitsFor ->
NylasAPI.makeRequest.callCount is 1
NylasAPIRequest.prototype.run.callCount is 1
runs ->
NylasAPI.makeRequest.calls[0].args[0].beforeProcessing({})
NylasAPIRequest.prototype.run.calls[0].args[0].beforeProcessing({})
expect(@task._removeLock).toHaveBeenCalledWith(@threadAMesage1)
it "should make no more than 10 requests at once", ->
resolves = []
spyOn(@task, '_removeLock')
spyOn(NylasAPI, 'makeRequest').andCallFake ->
spyOn(NylasAPIRequest.prototype, 'run').andCallFake ->
new Promise (resolve, reject) -> resolves.push(resolve)
threads = []
@ -400,7 +401,7 @@ describe "ChangeMailTask", ->
resolves = []
rejects = []
spyOn(@task, '_removeLock')
spyOn(NylasAPI, 'makeRequest').andCallFake ->
spyOn(NylasAPIRequest.prototype, 'run').andCallFake ->
new Promise (resolve, reject) ->
resolves.push(resolve)
rejects.push(reject)

View file

@ -1,5 +1,6 @@
{DestroyCategoryTask,
NylasAPI,
NylasAPIRequest,
Task,
Category,
AccountStore,
@ -72,7 +73,7 @@ describe "DestroyCategoryTask", ->
describe "when request succeeds", ->
beforeEach ->
spyOn(NylasAPI, "makeRequest").andCallFake -> Promise.resolve("null")
spyOn(NylasAPIRequest.prototype, "run").andCallFake -> Promise.resolve("null")
spyOn(NylasAPI, "incrementRemoteChangeLock")
it "blocks other remote changes to that category", ->
@ -84,32 +85,32 @@ describe "DestroyCategoryTask", ->
makeAccount(usesLabels: true)
task = makeTask()
task.performRemote()
expect(pathOf(NylasAPI.makeRequest)).toBe "/labels/server-444"
expect(pathOf(NylasAPIRequest.prototype.run)).toBe "/labels/server-444"
it "sends API req to /folders if user uses folders", ->
makeAccount(usesFolders: true)
task = makeTask()
task.performRemote()
expect(pathOf(NylasAPI.makeRequest)).toBe "/folders/server-444"
expect(pathOf(NylasAPIRequest.prototype.run)).toBe "/folders/server-444"
it "sends DELETE request", ->
makeAccount()
task = makeTask()
task.performRemote()
expect(methodOf(NylasAPI.makeRequest)).toBe "DELETE"
expect(methodOf(NylasAPIRequest.prototype.run)).toBe "DELETE"
it "sends the account id", ->
makeAccount()
task = makeTask()
task.performRemote()
expect(accountIdOf(NylasAPI.makeRequest)).toBe "account 123"
expect(accountIdOf(NylasAPIRequest.prototype.run)).toBe "account 123"
describe "when request fails", ->
beforeEach ->
makeAccount()
spyOn(NylasAPI, 'decrementRemoteChangeLock')
spyOn(NylasEnv, 'reportError')
spyOn(NylasAPI, 'makeRequest').andCallFake ->
spyOn(NylasAPIRequest.prototype, 'run').andCallFake ->
Promise.reject(new APIError({statusCode: 403}))
it "persists the category and notifies error", ->

View file

@ -1,7 +1,7 @@
import {
Task,
Model,
NylasAPI,
NylasAPIRequest,
DatabaseStore,
DestroyModelTask,
DatabaseTransaction} from 'nylas-exports'
@ -104,9 +104,9 @@ describe('DestroyModelTask', function destroyModelTask() {
});
it("makes a DELETE request to the Nylas API", () => {
spyOn(NylasAPI, "makeRequest").andReturn(Promise.resolve())
spyOn(NylasAPIRequest.prototype, "run").andReturn(Promise.resolve())
performRemote(() => {
const opts = NylasAPI.makeRequest.calls[0].args[0]
const opts = NylasAPIRequest.prototype.run.calls[0].args[0]
expect(opts.method).toBe("DELETE")
expect(opts.path).toBe("/endpoint/server-123")
expect(opts.accountId).toBe(this.defaultArgs.accountId)

View file

@ -1,6 +1,7 @@
_ = require 'underscore'
{NylasAPI,
NylasAPIRequest,
Event,
Actions,
APIError,
@ -49,9 +50,9 @@ describe "EventRSVPTask", ->
describe "performRemote", ->
it "should make the POST request to the message endpoint", ->
spyOn(NylasAPI, 'makeRequest').andCallFake => new Promise (resolve,reject) ->
spyOn(NylasAPIRequest.prototype, 'run').andCallFake => new Promise (resolve,reject) ->
@task.performRemote()
options = NylasAPI.makeRequest.mostRecentCall.args[0]
options = NylasAPIRequest.prototype.run.mostRecentCall.args[0]
expect(options.path).toBe("/send-rsvp")
expect(options.method).toBe('POST')
expect(options.accountId).toBe(@event.accountId)
@ -60,7 +61,7 @@ describe "EventRSVPTask", ->
describe "when the remote API request fails", ->
beforeEach ->
spyOn(NylasAPI, 'makeRequest').andCallFake -> Promise.reject(new APIError(body: '', statusCode: 400))
spyOn(NylasAPIRequest.prototype, 'run').andCallFake -> Promise.reject(new APIError(body: '', statusCode: 400))
it "should not be marked with the status", ->
@event = new Event

View file

@ -9,6 +9,7 @@ import {
Task,
SendDraftTask,
NylasAPI,
NylasAPIRequest,
SoundRegistry,
SyncbackMetadataTask,
} from 'nylas-exports';
@ -82,7 +83,7 @@ describe('SendDraftTask', function sendDraftTask() {
})],
};
spyOn(NylasAPI, 'makeRequest').andCallFake((options) => {
spyOn(NylasAPIRequest.prototype, 'run').andCallFake((options) => {
if (options.success) { options.success(this.response); }
return Promise.resolve(this.response);
})
@ -109,9 +110,9 @@ describe('SendDraftTask', function sendDraftTask() {
it("makes a send request with the correct data", () => {
waitsForPromise(() => this.task.performRemote().then(() => {
expect(NylasAPI.makeRequest).toHaveBeenCalled();
expect(NylasAPI.makeRequest.callCount).toBe(1);
const options = NylasAPI.makeRequest.mostRecentCall.args[0];
expect(NylasAPIRequest.prototype.run).toHaveBeenCalled();
expect(NylasAPIRequest.prototype.run.callCount).toBe(1);
const options = NylasAPIRequest.prototype.run.mostRecentCall.args[0];
expect(options.path).toBe("/send");
expect(options.method).toBe('POST');
expect(options.accountId).toBe(TEST_ACCOUNT_ID);
@ -121,16 +122,16 @@ describe('SendDraftTask', function sendDraftTask() {
it("should pass returnsModel:false", () => {
waitsForPromise(() => this.task.performRemote().then(() => {
expect(NylasAPI.makeRequest.calls.length).toBe(1);
const options = NylasAPI.makeRequest.mostRecentCall.args[0];
expect(NylasAPIRequest.prototype.run.calls.length).toBe(1);
const options = NylasAPIRequest.prototype.run.mostRecentCall.args[0];
expect(options.returnsModel).toBe(false);
}));
});
it("should always send the draft body in the request body (joined attribute check)", () => {
waitsForPromise(() => this.task.performRemote().then(() => {
expect(NylasAPI.makeRequest.calls.length).toBe(1);
const options = NylasAPI.makeRequest.mostRecentCall.args[0];
expect(NylasAPIRequest.prototype.run.calls.length).toBe(1);
const options = NylasAPIRequest.prototype.run.mostRecentCall.args[0];
expect(options.body.body).toBe('hello world');
}));
});
@ -224,7 +225,7 @@ describe('SendDraftTask', function sendDraftTask() {
describe("when there are errors", () => {
beforeEach(() => {
spyOn(Actions, 'sendDraftFailed');
jasmine.unspy(NylasAPI, "makeRequest");
jasmine.unspy(NylasAPIRequest.prototype, "run");
});
it("notifies of a permanent error of misc error types", () => {
@ -245,7 +246,7 @@ describe('SendDraftTask', function sendDraftTask() {
});
it("retries the task if 'Invalid message public id'", () => {
spyOn(NylasAPI, 'makeRequest').andCallFake((options) => {
spyOn(NylasAPIRequest.prototype, 'run').andCallFake((options) => {
if (options.body.reply_to_message_id) {
const err = new APIError({body: "Invalid message public id"});
return Promise.reject(err);
@ -259,10 +260,10 @@ describe('SendDraftTask', function sendDraftTask() {
waitsForPromise(() => {
return this.task.performRemote(this.draft)
.then(() => {
expect(NylasAPI.makeRequest).toHaveBeenCalled();
expect(NylasAPI.makeRequest.callCount).toEqual(2);
const req1 = NylasAPI.makeRequest.calls[0].args[0];
const req2 = NylasAPI.makeRequest.calls[1].args[0];
expect(NylasAPIRequest.prototype.run).toHaveBeenCalled();
expect(NylasAPIRequest.prototype.run.callCount).toEqual(2);
const req1 = NylasAPIRequest.prototype.run.calls[0].args[0];
const req2 = NylasAPIRequest.prototype.run.calls[1].args[0];
expect(req1.body.reply_to_message_id).toBe("reply-123");
expect(req1.body.thread_id).toBe("thread-123");
@ -273,7 +274,7 @@ describe('SendDraftTask', function sendDraftTask() {
});
it("retries the task if 'Invalid message public id'", () => {
spyOn(NylasAPI, 'makeRequest').andCallFake((options) => {
spyOn(NylasAPIRequest.prototype, 'run').andCallFake((options) => {
if (options.body.reply_to_message_id) {
return Promise.reject(new APIError({body: "Invalid thread"}));
}
@ -284,10 +285,10 @@ describe('SendDraftTask', function sendDraftTask() {
this.draft.replyToMessageId = "reply-123";
this.draft.threadId = "thread-123";
waitsForPromise(() => this.task.performRemote(this.draft).then(() => {
expect(NylasAPI.makeRequest).toHaveBeenCalled();
expect(NylasAPI.makeRequest.callCount).toEqual(2);
const req1 = NylasAPI.makeRequest.calls[0].args[0];
const req2 = NylasAPI.makeRequest.calls[1].args[0];
expect(NylasAPIRequest.prototype.run).toHaveBeenCalled();
expect(NylasAPIRequest.prototype.run.callCount).toEqual(2);
const req1 = NylasAPIRequest.prototype.run.calls[0].args[0];
const req2 = NylasAPIRequest.prototype.run.calls[1].args[0];
expect(req1.body.reply_to_message_id).toBe("reply-123");
expect(req1.body.thread_id).toBe("thread-123");
@ -299,7 +300,7 @@ describe('SendDraftTask', function sendDraftTask() {
it("notifies of a permanent error on 500 errors", () => {
const thrownError = new APIError({statusCode: 500, body: "err"})
spyOn(NylasEnv, "reportError");
spyOn(NylasAPI, 'makeRequest').andReturn(Promise.reject(thrownError));
spyOn(NylasAPIRequest.prototype, 'run').andReturn(Promise.reject(thrownError));
waitsForPromise(() => this.task.performRemote().then((status) => {
expect(status[0]).toBe(Task.Status.Failed);
@ -311,7 +312,7 @@ describe('SendDraftTask', function sendDraftTask() {
it("notifies us and users of a permanent error on 400 errors", () => {
const thrownError = new APIError({statusCode: 400, body: "err"});
spyOn(NylasEnv, "reportError");
spyOn(NylasAPI, 'makeRequest').andReturn(Promise.reject(thrownError));
spyOn(NylasAPIRequest.prototype, 'run').andReturn(Promise.reject(thrownError));
waitsForPromise(() => this.task.performRemote().then((status) => {
expect(status[0]).toBe(Task.Status.Failed);
@ -340,7 +341,7 @@ describe('SendDraftTask', function sendDraftTask() {
`
spyOn(NylasEnv, "reportError");
spyOn(NylasAPI, 'makeRequest').andReturn(Promise.reject(thrownError));
spyOn(NylasAPIRequest.prototype, 'run').andReturn(Promise.reject(thrownError));
waitsForPromise(() => this.task.performRemote().then((status) => {
expect(status[0]).toBe(Task.Status.Failed);
@ -365,7 +366,7 @@ describe('SendDraftTask', function sendDraftTask() {
const expectedMessage = "This message could not be delivered to at least one recipient. (Note: other recipients may have received this message - you should check Sent Mail before re-sending this message.)"
spyOn(NylasEnv, "reportError");
spyOn(NylasAPI, 'makeRequest').andReturn(Promise.reject(thrownError));
spyOn(NylasAPIRequest.prototype, 'run').andReturn(Promise.reject(thrownError));
waitsForPromise(() => this.task.performRemote().then((status) => {
expect(status[0]).toBe(Task.Status.Failed);
expect(status[1]).toBe(thrownError);
@ -392,7 +393,7 @@ describe('SendDraftTask', function sendDraftTask() {
it("halts on 500s", () => {
const thrownError = new APIError({statusCode: 500, body: "err"});
spyOn(NylasAPI, 'makeRequest').andReturn(Promise.reject(thrownError));
spyOn(NylasAPIRequest.prototype, 'run').andReturn(Promise.reject(thrownError));
waitsForPromise(() => this.task.performRemote().then(() =>
this.expectBlockedChain()
))
@ -400,7 +401,7 @@ describe('SendDraftTask', function sendDraftTask() {
it("halts on 400s", () => {
const thrownError = new APIError({statusCode: 400, body: "err"});
spyOn(NylasAPI, 'makeRequest').andReturn(Promise.reject(thrownError));
spyOn(NylasAPIRequest.prototype, 'run').andReturn(Promise.reject(thrownError));
waitsForPromise(() => this.task.performRemote().then(() =>
this.expectBlockedChain()
))
@ -408,7 +409,7 @@ describe('SendDraftTask', function sendDraftTask() {
it("halts and retries on not permanent error codes", () => {
const thrownError = new APIError({statusCode: 409, body: "err"});
spyOn(NylasAPI, 'makeRequest').andReturn(Promise.reject(thrownError));
spyOn(NylasAPIRequest.prototype, 'run').andReturn(Promise.reject(thrownError));
waitsForPromise(() => this.task.performRemote().then(() =>
this.expectBlockedChain()
))
@ -416,7 +417,7 @@ describe('SendDraftTask', function sendDraftTask() {
it("halts on other errors", () => {
const thrownError = new Error("oh no");
spyOn(NylasAPI, 'makeRequest').andReturn(Promise.reject(thrownError));
spyOn(NylasAPIRequest.prototype, 'run').andReturn(Promise.reject(thrownError));
waitsForPromise(() => this.task.performRemote().then(() =>
this.expectBlockedChain()
))
@ -426,7 +427,7 @@ describe('SendDraftTask', function sendDraftTask() {
// Don't spy reportError to make sure to fail the test on unexpected
// errors
jasmine.unspy(NylasEnv, 'reportError');
spyOn(NylasAPI, 'makeRequest').andCallFake((options) => {
spyOn(NylasAPIRequest.prototype, 'run').andCallFake((options) => {
if (options.success) { options.success(this.response) }
return Promise.resolve(this.response);
});

View file

@ -1,4 +1,5 @@
{NylasAPI,
NylasAPIRequest,
Category,
AccountStore,
DatabaseStore,
@ -31,7 +32,7 @@ describe "SyncbackCategoryTask", ->
category: category
beforeEach ->
spyOn(NylasAPI, "makeRequest").andCallFake ->
spyOn(NylasAPIRequest.prototype, "run").andCallFake ->
Promise.resolve(id: "server-444")
spyOn(DatabaseTransaction.prototype, "persistModel")
@ -39,25 +40,25 @@ describe "SyncbackCategoryTask", ->
makeAccount(usesLabels: true)
task = makeTask()
task.performRemote({})
expect(pathOf(NylasAPI.makeRequest)).toBe "/labels"
expect(pathOf(NylasAPIRequest.prototype.run)).toBe "/labels"
it "sends API req to /folders if the account uses folders", ->
makeAccount(usesFolders: true)
task = makeTask()
task.performRemote({})
expect(pathOf(NylasAPI.makeRequest)).toBe "/folders"
expect(pathOf(NylasAPIRequest.prototype.run)).toBe "/folders"
it "sends the account id", ->
makeAccount()
task = makeTask()
task.performRemote({})
expect(accountIdOf(NylasAPI.makeRequest)).toBe "account 123"
expect(accountIdOf(NylasAPIRequest.prototype.run)).toBe "account 123"
it "sends the display name in the body", ->
makeAccount()
task = makeTask()
task.performRemote({})
expect(nameOf(NylasAPI.makeRequest)).toBe "important emails"
expect(nameOf(NylasAPIRequest.prototype.run)).toBe "important emails"
it "adds server id to the category, then saves the category", ->
makeAccount()

View file

@ -6,6 +6,7 @@ import {
Contact,
SyncbackDraftFilesTask,
NylasAPI,
NylasAPIRequest,
} from 'nylas-exports';
const DBt = DatabaseTransaction.prototype;
@ -40,7 +41,7 @@ describe('SyncbackDraftFilesTask', function syncbackDraftFilesTask() {
spyOn(DBt, 'persistModel');
spyOn(fs, 'createReadStream').andReturn("stub");
spyOn(NylasAPI, 'makeRequest').andCallFake((options) => {
spyOn(NylasAPIRequest.prototype, 'run').andCallFake((options) => {
let response = this.response;
if (options.path === '/files') {
@ -66,9 +67,9 @@ describe('SyncbackDraftFilesTask', function syncbackDraftFilesTask() {
advanceClock();
// uploads should be queued, but not the send
expect(NylasAPI.makeRequest.callCount).toEqual(2);
expect(NylasAPI.makeRequest.calls[0].args[0].formData).toEqual({file: {value: 'stub', options: { filename: 'test-file-1.png' } } });
expect(NylasAPI.makeRequest.calls[1].args[0].formData).toEqual({file: {value: 'stub', options: { filename: 'test-file-2.png' } } });
expect(NylasAPIRequest.prototype.run.callCount).toEqual(2);
expect(NylasAPIRequest.prototype.run.calls[0].args[0].formData).toEqual({file: {value: 'stub', options: { filename: 'test-file-1.png' } } });
expect(NylasAPIRequest.prototype.run.calls[1].args[0].formData).toEqual({file: {value: 'stub', options: { filename: 'test-file-2.png' } } });
// finish all uploads
expect(taskPromise.isFulfilled()).toBe(false);
@ -108,8 +109,8 @@ describe('SyncbackDraftFilesTask', function syncbackDraftFilesTask() {
// Only upload `bbb` should be sent, upload `aaa` should be deleted
// because it was not present in the draft body.
expect(NylasAPI.makeRequest.callCount).toEqual(1);
expect(NylasAPI.makeRequest.calls[0].args[0].formData).toEqual({file: {value: 'stub', options: { filename: 'test-file-2.png' } } });
expect(NylasAPIRequest.prototype.run.callCount).toEqual(1);
expect(NylasAPIRequest.prototype.run.calls[0].args[0].formData).toEqual({file: {value: 'stub', options: { filename: 'test-file-2.png' } } });
this.resolveAll();
advanceClock();
expect(DBt.persistModel).toHaveBeenCalled();

View file

@ -13,6 +13,7 @@ import {
Task,
APIError,
NylasAPI,
NylasAPIRequest,
} from 'nylas-exports';
const inboxError = {
@ -128,21 +129,21 @@ describe('SyncbackDraftTask', function syncbackDraftTask() {
describe("performRemote", () => {
beforeEach(() => {
spyOn(NylasAPI, 'makeRequest').andReturn(Promise.resolve(remoteDraft().toJSON()))
spyOn(NylasAPIRequest.prototype, 'run').andReturn(Promise.resolve(remoteDraft().toJSON()))
});
it("does nothing if no draft can be found in the db", () => {
const task = new SyncbackDraftTask("missingDraftId");
waitsForPromise(() => task.performRemote().then(() => {
expect(NylasAPI.makeRequest).not.toHaveBeenCalled();
expect(NylasAPIRequest.prototype.run).not.toHaveBeenCalled();
}));
});
it("should start an API request with the Message JSON", () => {
const task = new SyncbackDraftTask("localDraftId")
waitsForPromise(() => task.performRemote().then(() => {
expect(NylasAPI.makeRequest).toHaveBeenCalled();
const reqBody = NylasAPI.makeRequest.mostRecentCall.args[0].body;
expect(NylasAPIRequest.prototype.run).toHaveBeenCalled();
const reqBody = NylasAPIRequest.prototype.run.mostRecentCall.args[0].body;
expect(reqBody.subject).toEqual(testData.subject);
expect(reqBody.body).toEqual(testData.body);
}));
@ -151,8 +152,8 @@ describe('SyncbackDraftTask', function syncbackDraftTask() {
it("should do a PUT when the draft has already been saved", () => {
const task = new SyncbackDraftTask("remoteDraftId")
waitsForPromise(() => task.performRemote().then(() => {
expect(NylasAPI.makeRequest).toHaveBeenCalled();
const options = NylasAPI.makeRequest.mostRecentCall.args[0];
expect(NylasAPIRequest.prototype.run).toHaveBeenCalled();
const options = NylasAPIRequest.prototype.run.mostRecentCall.args[0];
expect(options.path).toBe("/drafts/remoteid1234");
expect(options.accountId).toBe("abc123");
expect(options.method).toBe('PUT');
@ -162,8 +163,8 @@ describe('SyncbackDraftTask', function syncbackDraftTask() {
it("should do a POST when the draft is unsaved", () => {
const task = new SyncbackDraftTask("localDraftId");
waitsForPromise(() => task.performRemote().then(() => {
expect(NylasAPI.makeRequest).toHaveBeenCalled();
const options = NylasAPI.makeRequest.mostRecentCall.args[0];
expect(NylasAPIRequest.prototype.run).toHaveBeenCalled();
const options = NylasAPIRequest.prototype.run.mostRecentCall.args[0];
expect(options.path).toBe("/drafts");
expect(options.accountId).toBe("abc123");
expect(options.method).toBe('POST');
@ -185,8 +186,8 @@ describe('SyncbackDraftTask', function syncbackDraftTask() {
it("should pass returnsModel:false so that the draft can be manually removed/added to the database, accounting for its ID change", () => {
const task = new SyncbackDraftTask("localDraftId");
waitsForPromise(() => task.performRemote().then(() => {
expect(NylasAPI.makeRequest).toHaveBeenCalled();
const options = NylasAPI.makeRequest.mostRecentCall.args[0];
expect(NylasAPIRequest.prototype.run).toHaveBeenCalled();
const options = NylasAPIRequest.prototype.run.mostRecentCall.args[0];
expect(options.returnsModel).toBe(false);
}));
});
@ -226,7 +227,7 @@ describe('SyncbackDraftTask', function syncbackDraftTask() {
describe("When the api throws errors", () => {
const stubAPI = (code, method) => {
spyOn(NylasAPI, "makeRequest").andReturn(Promise.reject(
spyOn(NylasAPIRequest.prototype, "run").andReturn(Promise.reject(
new APIError({
error: inboxError,
response: {statusCode: code},
@ -266,7 +267,7 @@ describe('SyncbackDraftTask', function syncbackDraftTask() {
});
it("fails on other JavaScript errors", () => {
spyOn(NylasAPI, "makeRequest").andReturn(Promise.reject(new TypeError()));
spyOn(NylasAPIRequest.prototype, "run").andReturn(Promise.reject(new TypeError()));
waitsForPromise(() => this.task.performRemote().then(([status]) => {
expect(status).toBe(Task.Status.Failed);
expect(this.task.refreshDraftReference).toHaveBeenCalled();

View file

@ -1,6 +1,7 @@
import {
Task,
NylasAPI,
NylasAPIRequest,
APIError,
Model,
DatabaseStore,
@ -20,7 +21,7 @@ describe('SyncbackModelTask', function syncbackModelTask() {
spyOn(DatabaseStore, "findBy").andReturn(Promise.resolve(this.testModel));
spyOn(NylasEnv, "reportError")
spyOn(NylasAPI, "makeRequest").andReturn(Promise.resolve({
spyOn(NylasAPIRequest.prototype, "run").andReturn(Promise.resolve({
version: 10,
id: "server-123",
}))
@ -93,7 +94,7 @@ describe('SyncbackModelTask', function syncbackModelTask() {
performRemote(() => {
expect(this.task.getRequestData).toHaveBeenCalled()
const opts = NylasAPI.makeRequest.calls[0].args[0]
const opts = NylasAPIRequest.prototype.run.calls[0].args[0]
expect(opts.path).toBe("/test/server-123")
expect(opts.method).toBe("PUT")
});
@ -104,7 +105,7 @@ describe('SyncbackModelTask', function syncbackModelTask() {
performRemote(() => {
expect(this.task.getRequestData).toHaveBeenCalled()
const opts = NylasAPI.makeRequest.calls[0].args[0]
const opts = NylasAPIRequest.prototype.run.calls[0].args[0]
expect(opts.path).toBe("/test")
expect(opts.method).toBe("POST")
});
@ -128,7 +129,7 @@ describe('SyncbackModelTask', function syncbackModelTask() {
window.waitsForPromise(() => {
return task.performRemote().then(() => {
expect(task.getRequestData).toHaveBeenCalled()
const opts = NylasAPI.makeRequest.calls[0].args[0]
const opts = NylasAPIRequest.prototype.run.calls[0].args[0]
expect(opts.path).toBe("/override")
expect(opts.method).toBe("DELETE")
})
@ -143,7 +144,7 @@ describe('SyncbackModelTask', function syncbackModelTask() {
performRemote(() => {
expect(this.task.makeRequest).toHaveBeenCalled()
const opts = NylasAPI.makeRequest.calls[0].args[0]
const opts = NylasAPIRequest.prototype.run.calls[0].args[0]
expect(opts.path).toBe("/test")
expect(opts.method).toBe("POST")
expect(opts.accountId).toBe("account-123")
@ -167,18 +168,18 @@ describe('SyncbackModelTask', function syncbackModelTask() {
});
it("retries on retry-able API errors", () => {
jasmine.unspy(NylasAPI, "makeRequest");
jasmine.unspy(NylasAPIRequest.prototype, "run");
const err = new APIError({statusCode: 420});
spyOn(NylasAPI, "makeRequest").andReturn(Promise.reject(err))
spyOn(NylasAPIRequest.prototype, "run").andReturn(Promise.reject(err))
performRemote((status) => {
expect(status).toBe(Task.Status.Retry)
});
});
it("failes on permanent errors", () => {
jasmine.unspy(NylasAPI, "makeRequest");
jasmine.unspy(NylasAPIRequest.prototype, "run");
const err = new APIError({statusCode: 500});
spyOn(NylasAPI, "makeRequest").andReturn(Promise.reject(err))
spyOn(NylasAPIRequest.prototype, "run").andReturn(Promise.reject(err))
performRemote((status) => {
expect(status[0]).toBe(Task.Status.Failed)
expect(status[1].statusCode).toBe(500)

View file

@ -5,14 +5,14 @@ import {currentConfig, FAKE_DATA_PATH} from './helpers/config-helper';
import {assertBasicWindow, assertNoErrorsInLogs} from './helpers/shared-assertions';
import {clickRepeat, wait} from './helpers/client-actions';
describe('Clean app boot', ()=> {
beforeAll((done)=>{
describe('Clean app boot', () => {
beforeAll((done) => {
// Boot in dev mode with no arguments
this.app = new N1Launcher(['--dev'], N1Launcher.CLEAR_CONFIG);
this.app.onboardingWindowReady().finally(done);
});
afterAll((done)=> {
afterAll((done) => {
if (this.app && this.app.isRunning()) {
this.app.stop().finally(done);
} else {
@ -21,14 +21,14 @@ describe('Clean app boot', ()=> {
});
it("has the autoupdater pointing to the correct url when there's no config loaded", () => {
this.app.client.execute(()=>{
this.app.client.execute(() => {
const app = require('electron').remote.getGlobal('application');
return {
platform: process.platform,
arch: process.arch,
feedUrl: app.autoUpdateManager.feedURL,
};
}).then(({value})=>{
}).then(({value}) => {
const base = 'https://edgehill.nylas.com/update-check';
const config = currentConfig();
// NOTE: Since there's no loaded config yet (we haven't logged in),
@ -40,62 +40,62 @@ describe('Clean app boot', ()=> {
assertBasicWindow.call(this);
it('has width', (done)=> {
it('has width', (done) => {
this.app.client.getWindowWidth()
.then((result)=> expect(result).toBeGreaterThan(0) )
.then((result) => expect(result).toBeGreaterThan(0))
.finally(done);
});
it('has height', (done)=> {
it('has height', (done) => {
this.app.client.getWindowHeight()
.then((result)=> expect(result).toBeGreaterThan(0) )
.then((result) => expect(result).toBeGreaterThan(0))
.finally(done);
});
it('can sign up using Gmail', ()=> {
it('can sign up using Gmail', () => {
// TODO
});
it('can sign up using Exchange', (done)=> {
it('can sign up using Exchange', (done) => {
const client = this.app.client;
const fakeAccountJson = fs.readFileSync(
path.join(FAKE_DATA_PATH, 'account_exchange.json'),
'utf8'
);
client.execute((jsonStr)=> {
client.execute((jsonStr) => {
// Monkeypatch NylasAPI and EdgehillAPI
const json = JSON.parse(jsonStr);
$n._nylasApiMakeRequest = $n.NylasAPI.makeRequest;
$n._nylasApiMakeRequest = $n.NylasAPIRequest.run;
$n._edgehillRequest = $n.EdgehillAPI.makeRequest;
$n.NylasAPI.makeRequest = ()=> {
$n.NylasAPIRequest.run = () => {
return Promise.resolve(json);
};
$n.EdgehillAPI.makeRequest = ({success})=> {
$n.EdgehillAPI.makeRequest = ({success}) => {
success(json);
};
}, fakeAccountJson)
.then(()=> clickRepeat(client, '.btn-continue', {times: 3, interval: 500}))
.then(()=> client.click('.provider.exchange'))
.then(()=> wait(500))
.then(()=> client.click('input[data-field="name"]'))
.then(()=> client.keys('name'))
.then(()=> client.click('input[data-field="email"]'))
.then(()=> client.keys('email@nylas.com'))
.then(()=> client.click('input[data-field="password"]'))
.then(()=> client.keys('password'))
.then(()=> client.click('.btn-add-account'))
.then(()=> wait(500))
.then(()=> {
.then(() => clickRepeat(client, '.btn-continue', {times: 3, interval: 500}))
.then(() => client.click('.provider.exchange'))
.then(() => wait(500))
.then(() => client.click('input[data-field="name"]'))
.then(() => client.keys('name'))
.then(() => client.click('input[data-field="email"]'))
.then(() => client.keys('email@nylas.com'))
.then(() => client.click('input[data-field="password"]'))
.then(() => client.keys('password'))
.then(() => client.click('.btn-add-account'))
.then(() => wait(500))
.then(() => {
// Expect the onboarding window to have no errors at this point
return assertNoErrorsInLogs(client);
})
.then(()=> client.click('button.btn-large'))
.then(()=> wait(500))
.then(()=> client.click('.btn-get-started'))
.then(()=> wait(500))
.then(()=> N1Launcher.waitUntilMatchingWindowLoaded(client, N1Launcher.mainWindowLoadedMatcher))
.then(()=> {
.then(() => client.click('button.btn-large'))
.then(() => wait(500))
.then(() => client.click('.btn-get-started'))
.then(() => wait(500))
.then(() => N1Launcher.waitUntilMatchingWindowLoaded(client, N1Launcher.mainWindowLoadedMatcher))
.then(() => {
// Expect the main window logs to contain no errors
// This will run on the main window because waitUntilMatchingWindowLoaded
// focuses the window after its loaded

View file

@ -60,7 +60,11 @@ export default class OAuthSignInPage extends React.Component {
clearTimeout(this._pollTimer);
if (json && json.body) {
ipcRenderer.removeListener('browser-window-focus', onWindowFocused);
this.props.onSuccess(json.body);
let body = json
if (json.body) {
body = json.body
}
this.props.onSuccess(body);
} else {
delay = Math.min(delay * 1.2, 10000);
this._pollTimer = setTimeout(poll, delay);