From 52d065a38d1a3ac91683593d7791dbc975185565 Mon Sep 17 00:00:00 2001 From: Dick Choi Date: Wed, 24 Aug 2016 03:00:49 +0900 Subject: [PATCH] `init` dataApi method test --- .babelrc | 11 +++ .../main/lib/{dataApi.js => dataApi/index.js} | 3 +- browser/main/lib/dataApi/init.js | 77 +++++++++++++++++ package.json | 19 ++++- tests/.gitignore | 1 + tests/dataApi/init.js | 83 +++++++++++++++++++ tests/dummy/data.json | 28 +++++++ 7 files changed, 219 insertions(+), 3 deletions(-) rename browser/main/lib/{dataApi.js => dataApi/index.js} (99%) create mode 100644 browser/main/lib/dataApi/init.js create mode 100644 tests/.gitignore create mode 100644 tests/dataApi/init.js create mode 100644 tests/dummy/data.json diff --git a/.babelrc b/.babelrc index 1d3c91a6..c694b493 100644 --- a/.babelrc +++ b/.babelrc @@ -3,6 +3,17 @@ "env": { "development": { "presets": ["react-hmre"] + }, + "test": { + "presets": ["react", "es2015"], + "plugins": [ + [ + "module-alias", + [ + { "src": "./browser", "expose": "browser" } + ] + ] + ] } } } diff --git a/browser/main/lib/dataApi.js b/browser/main/lib/dataApi/index.js similarity index 99% rename from browser/main/lib/dataApi.js rename to browser/main/lib/dataApi/index.js index 51ae52bb..464d05d2 100644 --- a/browser/main/lib/dataApi.js +++ b/browser/main/lib/dataApi/index.js @@ -131,6 +131,7 @@ function init () { caches = JSON.parse(localStorage.getItem('storages')) if (!_.isArray(caches)) throw new Error('Cached data is not valid.') } catch (e) { + throw e console.error(e) caches = [] localStorage.setItem('storages', JSON.stringify(caches)) @@ -548,7 +549,7 @@ function moveNote (storageKey, folderKey, noteKey, newStorageKey, newFolderKey) .then(() => note.toJSON()) } -export default { +module.exports = { init, addStorage, removeStorage, diff --git a/browser/main/lib/dataApi/init.js b/browser/main/lib/dataApi/init.js new file mode 100644 index 00000000..316ea56d --- /dev/null +++ b/browser/main/lib/dataApi/init.js @@ -0,0 +1,77 @@ +'use strict' +const _ = require('lodash') +const sander = require('sander') +const path = require('path') + +function init () { + let fetchStorages = function () { + let rawStorages + try { + rawStorages = JSON.parse(window.localStorage.getItem('storages')) + if (!_.isArray(rawStorages)) throw new Error('Cached data is not valid.') + } catch (e) { + console.error(e) + rawStorages = [] + window.localStorage.setItem('storages', JSON.stringify(rawStorages)) + } + return Promise.all(rawStorages + .map(function assignFoldersToStorage (rawStorage) { + let data + let boostnoteJSONPath = path.join(rawStorage.path, 'boostnote.json') + try { + data = JSON.parse(sander.readFileSync(boostnoteJSONPath)) + if (!_.isArray(data.folders)) throw new Error('folders should be an array.') + rawStorage.folders = data.folders + } catch (err) { + if (err.code === 'ENOENT') { + console.warn('boostnote.json file doesn\'t exist the given path') + } else { + console.error(err) + } + rawStorage.folders = [] + } + return Promise.resolve(rawStorage) + })) + } + + let fetchNotes = function (storages) { + let notes = [] + + storages + .forEach((storage) => { + storage.folders.forEach((folder) => { + let dataPath = path.join(storage.path, folder.key, 'data.json') + let data + try { + data = JSON.parse(sander.readFileSync(dataPath)) + if (!_.isArray(data.notes)) throw new Error('notes should be an array.') + } catch (e) { + // Remove folder if fetching failed. + console.error('Failed to load data: %s', dataPath) + storage.folders = storage.folders.filter((_folder) => _folder.key !== folder.key) + data = {notes: []} + } + data.notes.forEach((note) => { + note.storage = storage.key + note.folder = folder.key + notes.push(note) + }) + }) + }) + return Promise.resolve({ + storages, + notes + }) + } + + return Promise.resolve(fetchStorages()) + .then((storages) => { + storages = storages.filter((storage) => { + if (!_.isObject(storage)) return false + return true + }) + return storages + }) + .then(fetchNotes) +} +module.exports = init diff --git a/package.json b/package.json index 79edaa85..288172bf 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "webpack": "webpack-dev-server --hot --inline --config webpack.config.js", "postinstall": "npm run vendor", "vendor": "oh-my-cdn", - "compile": "grunt compile" + "compile": "grunt compile", + "test": "ava" }, "config": { "electron-version": "1.2.8" @@ -60,20 +61,25 @@ "superagent-promise": "^1.0.3" }, "devDependencies": { + "ava": "^0.16.0", + "babel": "^6.5.2", "babel-core": "^6.3.26", "babel-loader": "^6.2.0", + "babel-plugin-module-alias": "^1.6.0", "babel-plugin-react-transform": "^2.0.0", "babel-preset-es2015": "^6.3.13", "babel-preset-react": "^6.3.13", "babel-preset-react-hmre": "^1.0.1", + "babel-register": "^6.11.6", "css-loader": "^0.19.0", "devtron": "^1.1.0", + "dom-storage": "^2.0.2", "electron-packager": "^6.0.0", "electron-prebuilt": "^1.2.8", - "electron-release": "^2.2.0", "grunt": "^0.4.5", "grunt-electron-installer": "^1.2.0", "history": "^1.17.0", + "jsdom": "^9.4.2", "merge-stream": "^1.0.0", "nib": "^1.1.0", "oh-my-cdn": "^0.1.1", @@ -99,5 +105,14 @@ "globals": [ "localStorage" ] + }, + "ava": { + "files": [ + "tests/**/*.js" + ], + "require": [ + "babel-register" + ], + "babel": "inherit" } } diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 00000000..59ea0e6c --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1 @@ +sandbox/* diff --git a/tests/dataApi/init.js b/tests/dataApi/init.js new file mode 100644 index 00000000..95d5f581 --- /dev/null +++ b/tests/dataApi/init.js @@ -0,0 +1,83 @@ +const test = require('ava') +const init = require('browser/main/lib/dataApi/init') + +global.document = require('jsdom').jsdom('') +global.window = document.defaultView +global.navigator = window.navigator + +const Storage = require('dom-storage') +const localStorage = window.localStorage = global.localStorage = new Storage(null, { strict: true }) +const sander = require('sander') +const path = require('path') +const crypto = require('crypto') + +const dummyStoragePath = path.join(__dirname, '..', 'sandbox') +const dummyRawStorage = { + name: 'test', + key: crypto.randomBytes(6).toString('hex'), + path: dummyStoragePath +} + +test.serial('fetch storages and notes', (t) => { + const boostnoteJSONPath = path.join(dummyStoragePath, 'boostnote.json') + const dummyFolderKey = crypto.randomBytes(6).toString('hex') + const dummyFolders = [{ + key: dummyFolderKey, + name: 'test1', + color: '#f55' + }] + const dummyFolderDataJSONPath = path.join(dummyStoragePath, dummyFolderKey, 'data.json') + const dummyNotesJSONString = sander.readFileSync(path.join(__dirname, '../dummy/data.json')) + + return Promise.resolve() + .then(function before () { + localStorage.setItem('storages', JSON.stringify([dummyRawStorage])) + sander.writeFileSync(boostnoteJSONPath, JSON.stringify({folders: dummyFolders})) + sander.writeFileSync(dummyFolderDataJSONPath, dummyNotesJSONString) + }) + .then(function test () { + return init() + }) + .then(function assert (data) { + t.true(Array.isArray(data.storages)) + var targetStorage = data.storages.filter((storage) => storage.key === dummyRawStorage.key)[0] + t.not(targetStorage, null) + t.is(targetStorage.name, dummyRawStorage.name) + t.is(targetStorage.key, dummyRawStorage.key) + t.is(targetStorage.path, dummyRawStorage.path) + t.is(data.notes.length, 2) + data.notes.forEach((note) => { + t.is(note.folder, dummyFolderKey) + }) + + t.true(Array.isArray(data.notes)) + }) + .then(function after () { + localStorage.clear() + sander.unlinkSync(boostnoteJSONPath) + sander.unlinkSync(dummyFolderDataJSONPath) + }) +}) + +test.serial('Fetch storages. case: storage folder doesnt exist.', (t) => { + return Promise.resolve() + .then(function before () { + localStorage.setItem('storages', JSON.stringify([dummyRawStorage])) + }) + .then(function test () { + return init() + }) + .then(function assert (data) { + t.true(Array.isArray(data.storages)) + var targetStorage = data.storages.filter((storage) => storage.key === dummyRawStorage.key)[0] + t.not(targetStorage, null) + t.is(targetStorage.name, dummyRawStorage.name) + t.is(targetStorage.key, dummyRawStorage.key) + t.is(targetStorage.path, dummyRawStorage.path) + + t.true(Array.isArray(data.notes)) + }) + .then(function after () { + localStorage.clear() + }) +}) diff --git a/tests/dummy/data.json b/tests/dummy/data.json new file mode 100644 index 00000000..b3d78d5e --- /dev/null +++ b/tests/dummy/data.json @@ -0,0 +1,28 @@ +{"notes": + [ + { + "tags": [], + "title": "Footnote test", + "content": "# Footnote test\n\ntest test", + "type": "MARKDOWN_NOTE", + "folder": "fc6ba88e8ecf", + "key": "93c6ac2a7953", + "isStarred": false, + "createdAt": "2016-07-25T16:19:55.620Z", + "updatedAt": "2016-07-26T08:00:11.326Z", + "uniqueKey": "1714d46e36b5-fc6ba88e8ecf-93c6ac2a7953" + }, + { + "tags": [], + "title": "Checkbox test", + "content": "# Checkbox test\n\n- [x] Task1\n- [ ] Task2\n- [ ] Task3\n\n", + "type": "MARKDOWN_NOTE", + "folder": "fc6ba88e8ecf", + "key": "4568d84331d9", + "isStarred": false, + "createdAt": "2016-07-25T16:58:43.685Z", + "updatedAt": "2016-08-21T06:14:50.381Z", + "uniqueKey": "1714d46e36b5-fc6ba88e8ecf-4568d84331d9" + } + ] + }