Mailspring/internal_packages/thread-snooze/spec/snooze-utils-spec.es6
Juan Tejada d92506d8f1 fix(sync-status): Change old per model status, in favor of per folder
Summary:
Addresses T7275
Previously, we kept track of the sync status of each API model, and the progress
we'd made syncing all available models (e.g. all threads, messages, events, etc)

Given K2's set up, we are now keeping track of sync status per folder, i.e. what
percent of the folder's messages we've synced. This status is now reported from K2
to N1 via folder object deltas, and this commit rewrites the
NylasSyncStatusStore (in ES6) to reflect that.

The new Store keeps the sync state per account, which is the merged state of
per folder sync state, and delta connections state.
We also got rid of `CategoryStore.whenCategoriesReady` in favor of
`whenCategoryListSynced`, which is derived from the fact hat as long as we've
started syncing one folder, we've already synced the entire list of of folders/labels.

There are a couple of TODOs to be addressed in upcoming diffs:
- T7329 Restore the sidebar component to show sync progress, which was previously removed
- T7330 Figure out how to report sync progress per label, specifically, we are interested in knowing how much of the inbox we've synced, which is a label in Gmail. (This might be a non-issue if we sync the inbox very fast, first)

Depends on D3514

Test Plan: Manual

Reviewers: mark, evan

Reviewed By: evan

Differential Revision: https://phab.nylas.com/D3515
2016-12-15 11:17:20 -08:00

225 lines
9 KiB
JavaScript

import moment from 'moment'
import {
Actions,
TaskQueueStatusStore,
TaskFactory,
DatabaseStore,
Category,
Thread,
CategoryStore,
NylasSyncStatusStore,
} from 'nylas-exports'
import SnoozeUtils from '../lib/snooze-utils'
xdescribe('Snooze Utils', function snoozeUtils() {
beforeEach(() => {
this.name = 'Snoozed Folder'
this.accId = 123
spyOn(NylasSyncStatusStore, 'whenCategoryListSynced').andReturn(Promise.resolve())
})
describe('snoozedUntilMessage', () => {
it('returns correct message if no snooze date provided', () => {
expect(SnoozeUtils.snoozedUntilMessage()).toEqual('Snoozed')
});
describe('when less than 24 hours from now', () => {
it('returns correct message if snoozeDate is on the hour of the clock', () => {
const now9AM = window.testNowMoment().hour(9).minute(0)
const tomorrowAt8 = moment(now9AM).add(1, 'day').hour(8)
const result = SnoozeUtils.snoozedUntilMessage(tomorrowAt8, now9AM)
expect(result).toEqual('Snoozed until 8 AM')
});
it('returns correct message if snoozeDate otherwise', () => {
const now9AM = window.testNowMoment().hour(9).minute(0)
const snooze10AM = moment(now9AM).hour(10).minute(5)
const result = SnoozeUtils.snoozedUntilMessage(snooze10AM, now9AM)
expect(result).toEqual('Snoozed until 10:05 AM')
});
});
describe('when more than 24 hourse from now', () => {
it('returns correct message if snoozeDate is on the hour of the clock', () => {
// Jan 1
const now9AM = window.testNowMoment().month(0).date(1).hour(9).minute(0)
const tomorrowAt10 = moment(now9AM).add(1, 'day').hour(10)
const result = SnoozeUtils.snoozedUntilMessage(tomorrowAt10, now9AM)
expect(result).toEqual('Snoozed until Jan 2, 10 AM')
});
it('returns correct message if snoozeDate otherwise', () => {
// Jan 1
const now9AM = window.testNowMoment().month(0).date(1).hour(9).minute(0)
const tomorrowAt930 = moment(now9AM).add(1, 'day').minute(30)
const result = SnoozeUtils.snoozedUntilMessage(tomorrowAt930, now9AM)
expect(result).toEqual('Snoozed until Jan 2, 9:30 AM')
});
});
});
describe('createSnoozeCategory', () => {
beforeEach(() => {
this.category = new Category({
displayName: this.name,
accountId: this.accId,
clientId: 321,
serverId: 321,
})
spyOn(Actions, 'queueTask')
spyOn(TaskQueueStatusStore, 'waitForPerformRemote').andReturn(Promise.resolve())
spyOn(DatabaseStore, 'findBy').andReturn(Promise.resolve(this.category))
})
it('creates category with correct snooze name', () => {
SnoozeUtils.createSnoozeCategory(this.accId, this.name)
expect(Actions.queueTask).toHaveBeenCalled()
const task = Actions.queueTask.calls[0].args[0]
expect(task.category.displayName).toEqual(this.name)
expect(task.category.accountId).toEqual(this.accId)
});
it('resolves with the updated category that has been saved to the server', () => {
waitsForPromise(() => {
return SnoozeUtils.createSnoozeCategory(this.accId, this.name).then((result) => {
expect(DatabaseStore.findBy).toHaveBeenCalled()
expect(result).toBe(this.category)
})
})
});
it('rejects if the category could not be found in the database', () => {
this.category.serverId = null
jasmine.unspy(DatabaseStore, 'findBy')
spyOn(DatabaseStore, 'findBy').andReturn(Promise.resolve(this.category))
waitsForPromise(() => {
return SnoozeUtils.createSnoozeCategory(this.accId, this.name)
.then(() => {
throw new Error('SnoozeUtils.createSnoozeCategory should not resolve in this case!')
})
.catch((error) => {
expect(DatabaseStore.findBy).toHaveBeenCalled()
expect(error.message).toEqual('Could not create Snooze category')
})
})
});
it('rejects if the category could not be saved to the server', () => {
jasmine.unspy(DatabaseStore, 'findBy')
spyOn(DatabaseStore, 'findBy').andReturn(Promise.resolve(undefined))
waitsForPromise(() => {
return SnoozeUtils.createSnoozeCategory(this.accId, this.name)
.then(() => {
throw new Error('SnoozeUtils.createSnoozeCategory should not resolve in this case!')
})
.catch((error) => {
expect(DatabaseStore.findBy).toHaveBeenCalled()
expect(error.message).toEqual('Could not create Snooze category')
})
})
});
});
describe('getSnoozeCategory', () => {
it('resolves category if it exists in the category store', () => {
const categories = [
new Category({accountId: this.accId, name: 'inbox'}),
new Category({accountId: this.accId, displayName: this.name}),
]
spyOn(CategoryStore, 'categories').andReturn(categories)
spyOn(SnoozeUtils, 'createSnoozeCategory')
waitsForPromise(() => {
return SnoozeUtils.getSnoozeCategory(this.accountId, this.name)
.then((result) => {
expect(SnoozeUtils.createSnoozeCategory).not.toHaveBeenCalled()
expect(result).toBe(categories[1])
})
})
});
it('creates category if it does not exist', () => {
const categories = [
new Category({accountId: this.accId, name: 'inbox'}),
]
const snoozeCat = new Category({accountId: this.accId, displayName: this.name})
spyOn(CategoryStore, 'categories').andReturn(categories)
spyOn(SnoozeUtils, 'createSnoozeCategory').andReturn(Promise.resolve(snoozeCat))
waitsForPromise(() => {
return SnoozeUtils.getSnoozeCategory(this.accId, this.name)
.then((result) => {
expect(SnoozeUtils.createSnoozeCategory).toHaveBeenCalledWith(this.accId, this.name)
expect(result).toBe(snoozeCat)
})
})
});
});
describe('moveThreads', () => {
beforeEach(() => {
this.description = 'Snoozin';
this.snoozeCatsByAccount = {
123: new Category({accountId: 123, displayName: this.name, serverId: 'sr-1'}),
321: new Category({accountId: 321, displayName: this.name, serverId: 'sr-2'}),
}
this.inboxCatsByAccount = {
123: new Category({accountId: 123, name: 'inbox', serverId: 'sr-3'}),
321: new Category({accountId: 321, name: 'inbox', serverId: 'sr-4'}),
}
this.threads = [
new Thread({accountId: 123}),
new Thread({accountId: 123}),
new Thread({accountId: 321}),
]
this.getInboxCat = (accId) => [this.inboxCatsByAccount[accId]]
this.getSnoozeCat = (accId) => [this.snoozeCatsByAccount[accId]]
spyOn(DatabaseStore, 'modelify').andReturn(Promise.resolve(this.threads))
spyOn(TaskFactory, 'tasksForApplyingCategories').andReturn([])
spyOn(TaskQueueStatusStore, 'waitForPerformRemote').andReturn(Promise.resolve())
spyOn(Actions, 'queueTasks')
})
it('creates the tasks to move threads correctly when snoozing', () => {
const snooze = true
const description = this.description
waitsForPromise(() => {
return SnoozeUtils.moveThreads(this.threads, {snooze, description, getInboxCategory: this.getInboxCat, getSnoozeCategory: this.getSnoozeCat})
.then(() => {
expect(TaskFactory.tasksForApplyingCategories).toHaveBeenCalled()
expect(Actions.queueTasks).toHaveBeenCalled()
const {threads, categoriesToAdd, categoriesToRemove, taskDescription} = TaskFactory.tasksForApplyingCategories.calls[0].args[0]
expect(threads).toBe(this.threads)
expect(categoriesToRemove('123')[0]).toBe(this.inboxCatsByAccount['123'])
expect(categoriesToRemove('321')[0]).toBe(this.inboxCatsByAccount['321'])
expect(categoriesToAdd('123')[0]).toBe(this.snoozeCatsByAccount['123'])
expect(categoriesToAdd('321')[0]).toBe(this.snoozeCatsByAccount['321'])
expect(taskDescription).toEqual(description)
})
})
});
it('creates the tasks to move threads correctly when unsnoozing', () => {
const snooze = false
const description = this.description
waitsForPromise(() => {
return SnoozeUtils.moveThreads(this.threads, {snooze, description, getInboxCategory: this.getInboxCat, getSnoozeCategory: this.getSnoozeCat})
.then(() => {
expect(TaskFactory.tasksForApplyingCategories).toHaveBeenCalled()
expect(Actions.queueTasks).toHaveBeenCalled()
const {threads, categoriesToAdd, categoriesToRemove, taskDescription} = TaskFactory.tasksForApplyingCategories.calls[0].args[0]
expect(threads).toBe(this.threads)
expect(categoriesToAdd('123')[0]).toBe(this.inboxCatsByAccount['123'])
expect(categoriesToAdd('321')[0]).toBe(this.inboxCatsByAccount['321'])
expect(categoriesToRemove('123')[0]).toBe(this.snoozeCatsByAccount['123'])
expect(categoriesToRemove('321')[0]).toBe(this.snoozeCatsByAccount['321'])
expect(taskDescription).toEqual(description)
})
})
});
});
});