From 1e3b346c94bcfbfab8a980093e9e7b2ebf8d5129 Mon Sep 17 00:00:00 2001 From: Ben Gotow Date: Mon, 5 Dec 2016 16:07:46 -0800 Subject: [PATCH] [local-sync] feat(specs): Add basic tests for folder sync --- .../FetchFolderList/gmail-bengotow.json | 174 ++++++++++++++++++ .../FetchFolderList/imap-inboxapptest1.json | 158 ++++++++++++++++ packages/local-sync/spec/helpers.js | 28 +++ .../spec/imap/fetch-folder-list-spec.js | 45 +++++ .../local-sync/spec/message-factory-spec.js | 26 ++- packages/local-sync/spec/threading-spec.js | 4 +- 6 files changed, 417 insertions(+), 18 deletions(-) create mode 100644 packages/local-sync/spec/fixtures/FetchFolderList/gmail-bengotow.json create mode 100644 packages/local-sync/spec/fixtures/FetchFolderList/imap-inboxapptest1.json create mode 100644 packages/local-sync/spec/helpers.js create mode 100644 packages/local-sync/spec/imap/fetch-folder-list-spec.js diff --git a/packages/local-sync/spec/fixtures/FetchFolderList/gmail-bengotow.json b/packages/local-sync/spec/fixtures/FetchFolderList/gmail-bengotow.json new file mode 100644 index 000000000..fc9b76d69 --- /dev/null +++ b/packages/local-sync/spec/fixtures/FetchFolderList/gmail-bengotow.json @@ -0,0 +1,174 @@ +{ + "boxes": { + "GitHub": { + "attribs": ["\\HasChildren"], + "delimiter": "/", + "children": { + "Electron": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": "[Circular]" + }, + "N1": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": "[Circular]" + } + }, + "parent": null + }, + "INBOX": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": null + }, + "Junk (Gmail)": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": null + }, + "N1-Snoozed": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": null + }, + "Notes": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": null + }, + "Receipts": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": null + }, + "Recruiters": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": null + }, + "Sentry": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": null + }, + "[Gmail]": { + "attribs": ["\\HasChildren", "\\Noselect"], + "delimiter": "/", + "children": { + "All Mail": { + "attribs": ["\\All", "\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": "[Circular]", + "special_use_attrib": "\\All" + }, + "Drafts": { + "attribs": ["\\Drafts", "\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": "[Circular]", + "special_use_attrib": "\\Drafts" + }, + "Important": { + "attribs": ["\\HasNoChildren", "\\Important"], + "delimiter": "/", + "children": null, + "parent": "[Circular]", + "special_use_attrib": "\\Important" + }, + "Sent Mail": { + "attribs": ["\\HasNoChildren", "\\Sent"], + "delimiter": "/", + "children": null, + "parent": "[Circular]", + "special_use_attrib": "\\Sent" + }, + "Spam": { + "attribs": ["\\HasNoChildren", "\\Junk"], + "delimiter": "/", + "children": null, + "parent": "[Circular]", + "special_use_attrib": "\\Junk" + }, + "Starred": { + "attribs": ["\\Flagged", "\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": "[Circular]", + "special_use_attrib": "\\Flagged" + }, + "Trash": { + "attribs": ["\\HasNoChildren", "\\Trash"], + "delimiter": "/", + "children": null, + "parent": "[Circular]", + "special_use_attrib": "\\Trash" + } + }, + "parent": null + } + }, + "expectedFolders": [{ + "role": "trash", + "name": "[Gmail]/Trash" + }, { + "role": "spam", + "name": "[Gmail]/Spam" + }, { + "role": "all", + "name": "[Gmail]/All Mail" + }], + "expectedLabels": [{ + "role": "starred", + "name": "[Gmail]/Starred" + }, { + "role": "sent", + "name": "[Gmail]/Sent Mail" + }, { + "role": "important", + "name": "[Gmail]/Important" + }, { + "role": "drafts", + "name": "[Gmail]/Drafts" + }, { + "role": null, + "name": "Sentry" + }, { + "role": null, + "name": "Recruiters" + }, { + "role": null, + "name": "Receipts" + }, { + "role": null, + "name": "Notes" + }, { + "role": null, + "name": "N1-Snoozed" + }, { + "role": null, + "name": "Junk (Gmail)" + }, { + "role": "inbox", + "name": "INBOX" + }, { + "role": null, + "name": "GitHub" + }, { + "role": null, + "name": "GitHub/N1" + }, { + "role": null, + "name": "GitHub/Electron" + }] +} diff --git a/packages/local-sync/spec/fixtures/FetchFolderList/imap-inboxapptest1.json b/packages/local-sync/spec/fixtures/FetchFolderList/imap-inboxapptest1.json new file mode 100644 index 000000000..2c2148fa8 --- /dev/null +++ b/packages/local-sync/spec/fixtures/FetchFolderList/imap-inboxapptest1.json @@ -0,0 +1,158 @@ +{ + "boxes": { + "2016": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": null + }, + "INBOX": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": null + }, + "Archive": { + "attribs": ["\\HasNoChildren", "\\Archive"], + "delimiter": "/", + "children": null, + "parent": null, + "special_use_attrib": "\\Archive" + }, + "Arts": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": null + }, + "Boîte de réception": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": null + }, + "Drafts": { + "attribs": ["\\HasNoChildren", "\\Drafts"], + "delimiter": "/", + "children": null, + "parent": null, + "special_use_attrib": "\\Drafts" + }, + "Fondue": { + "children": { + "Savoyarde": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": "[Circular]" + } + } + }, + "Housse": { + "children": { + "De": { + "children": { + "Bateau": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": "[Circular]" + }, + "Rateau": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": "[Circular]" + } + } + } + } + }, + "JJJJJJJ JJJJJJJJ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": null + }, + "N1-Snoozed": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": null + }, + "Over the top": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": null + }, + "Sent": { + "attribs": ["\\HasNoChildren", "\\Sent"], + "delimiter": "/", + "children": null, + "parent": null, + "special_use_attrib": "\\Sent" + }, + "Spam": { + "attribs": ["\\HasNoChildren", "\\Junk"], + "delimiter": "/", + "children": null, + "parent": null, + "special_use_attrib": "\\Junk" + }, + "Taxes": { + "attribs": ["\\HasNoChildren"], + "delimiter": "/", + "children": null, + "parent": null + }, + "Trash": { + "attribs": ["\\HasNoChildren", "\\Trash"], + "delimiter": "/", + "children": null, + "parent": null, + "special_use_attrib": "\\Trash" + } + }, + "expectedFolders": [{ + "role": "trash", + "name": "Trash" + }, { + "role": null, + "name": "Taxes" + }, { + "role": "spam", + "name": "Spam" + }, { + "role": "sent", + "name": "Sent" + }, { + "role": null, + "name": "Over the top" + }, { + "role": null, + "name": "N1-Snoozed" + }, { + "role": null, + "name": "JJJJJJJ JJJJJJJJ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1" + }, { + "role": "drafts", + "name": "Drafts" + }, { + "role": null, + "name": "Boîte de réception" + }, { + "role": null, + "name": "Arts" + }, { + "role": null, + "name": "Archive" + }, { + "role": "inbox", + "name": "INBOX" + }, { + "role": null, + "name": "2016" + }], + "expectedLabels": [] +} diff --git a/packages/local-sync/spec/helpers.js b/packages/local-sync/spec/helpers.js new file mode 100644 index 000000000..d767f5633 --- /dev/null +++ b/packages/local-sync/spec/helpers.js @@ -0,0 +1,28 @@ +const fs = require('fs'); +const path = require('path'); + +const FIXTURES_PATH = path.join(__dirname, 'fixtures'); +const ACCOUNT_ID = 'test-account-id'; + +function forEachJSONFixture(relativePath, callback) { + const fixturesDir = path.join(FIXTURES_PATH, relativePath); + const filenames = fs.readdirSync(fixturesDir).filter(f => f.endsWith('.json')); + filenames.forEach((filename) => { + const json = JSON.parse(fs.readFileSync(path.join(fixturesDir, filename))); + callback(filename, json); + }); +} + +const silentLogger = { + info: () => {}, + warn: () => {}, + debug: () => {}, + error: () => {}, +} + +module.exports = { + FIXTURES_PATH, + ACCOUNT_ID, + silentLogger, + forEachJSONFixture, +} diff --git a/packages/local-sync/spec/imap/fetch-folder-list-spec.js b/packages/local-sync/spec/imap/fetch-folder-list-spec.js new file mode 100644 index 000000000..ed2580ea1 --- /dev/null +++ b/packages/local-sync/spec/imap/fetch-folder-list-spec.js @@ -0,0 +1,45 @@ + +const FetchFolderList = require('../../src/local-sync-worker/imap/fetch-folder-list'); +const LocalDatabaseConnector = require('../../src/shared/local-database-connector'); +const {forEachJSONFixture, ACCOUNT_ID, silentLogger} = require('../helpers'); + +describe("FetchFolderList", function FetchFolderListSpecs() { + beforeEach(() => { + waitsForPromise(async () => { + await LocalDatabaseConnector.ensureAccountDatabase(ACCOUNT_ID); + this.db = await LocalDatabaseConnector.forAccount(ACCOUNT_ID); + + this.stubImapBoxes = null; + this.imap = { + getBoxes: () => { + return Promise.resolve(this.stubImapBoxes); + }, + }; + }); + }); + + afterEach(() => { + LocalDatabaseConnector.destroyAccountDatabase(ACCOUNT_ID) + }) + + describe("initial syncing", () => { + forEachJSONFixture('FetchFolderList', (filename, json) => { + it(`should create folders and labels correctly for boxes (${filename})`, () => { + waitsForPromise(async () => { + const {boxes, expectedFolders, expectedLabels} = json; + const provider = filename.split('-')[0]; + this.stubImapBoxes = boxes; + + const task = new FetchFolderList(provider, silentLogger); + await task.run(this.db, this.imap); + + const folders = await this.db.Folder.findAll(); + expect(folders.map((f) => { return {name: f.name, role: f.role} })).toEqual(expectedFolders); + + const labels = await this.db.Label.findAll(); + expect(labels.map(f => { return {name: f.name, role: f.role} })).toEqual(expectedLabels); + }); + }); + }); + }); +}); diff --git a/packages/local-sync/spec/message-factory-spec.js b/packages/local-sync/spec/message-factory-spec.js index c0643f26a..bd2ea44f0 100644 --- a/packages/local-sync/spec/message-factory-spec.js +++ b/packages/local-sync/spec/message-factory-spec.js @@ -1,35 +1,31 @@ -const path = require('path'); -const fs = require('fs'); const LocalDatabaseConnector = require('../src/shared/local-database-connector'); const {parseFromImap} = require('../src/shared/message-factory'); - -const FIXTURES_PATH = path.join(__dirname, 'fixtures') +const {forEachJSONFixture, ACCOUNT_ID} = require('./helpers'); describe('MessageFactory', function MessageFactorySpecs() { beforeEach(() => { waitsForPromise(async () => { - const accountId = 'test-account-id'; - await LocalDatabaseConnector.ensureAccountDatabase(accountId); - const db = await LocalDatabaseConnector.forAccount(accountId); + await LocalDatabaseConnector.ensureAccountDatabase(ACCOUNT_ID); + const db = await LocalDatabaseConnector.forAccount(ACCOUNT_ID); const folder = await db.Folder.create({ id: 'test-folder-id', - accountId: accountId, + accountId: ACCOUNT_ID, version: 1, name: 'Test Folder', role: null, }); - this.options = { accountId, db, folder }; + this.options = { accountId: ACCOUNT_ID, db, folder }; }) }) - describe("parseFromImap", () => { - const fixturesDir = path.join(FIXTURES_PATH, 'MessageFactory', 'parseFromImap'); - const filenames = fs.readdirSync(fixturesDir).filter(f => f.endsWith('.json')); + afterEach(() => { + LocalDatabaseConnector.destroyAccountDatabase(ACCOUNT_ID) + }) - filenames.forEach((filename) => { + describe("parseFromImap", () => { + forEachJSONFixture('MessageFactory/parseFromImap', (filename, json) => { it(`should correctly build message properties for ${filename}`, () => { - const inJSON = JSON.parse(fs.readFileSync(path.join(fixturesDir, filename))); - const {imapMessage, desiredParts, result} = inJSON; + const {imapMessage, desiredParts, result} = json; waitsForPromise(async () => { const actual = await parseFromImap(imapMessage, desiredParts, this.options); diff --git a/packages/local-sync/spec/threading-spec.js b/packages/local-sync/spec/threading-spec.js index 22e6a4615..f4d05ffa6 100644 --- a/packages/local-sync/spec/threading-spec.js +++ b/packages/local-sync/spec/threading-spec.js @@ -1,11 +1,9 @@ /* eslint global-require: 0 */ /* eslint import/no-dynamic-require: 0 */ -const path = require('path'); const detectThread = require('../src/new-message-processor/detect-thread'); const LocalDatabaseConnector = require('../src/shared/local-database-connector'); -const FIXTURES_PATH = path.join(__dirname, 'fixtures'); -const ACCOUNT_ID = 'test-account-threading'; +const {FIXTURES_PATH, ACCOUNT_ID} = require('./helpers') function messagesFromFixture({Message}, folder, name) { const {A, B} = require(`${FIXTURES_PATH}/Threading/${name}`)