From 0127d5143afdeea20044026a0f6cfff06f2bfa7c Mon Sep 17 00:00:00 2001 From: Dick Choi Date: Sat, 27 Aug 2016 22:13:32 +0900 Subject: [PATCH] createNote --- browser/main/lib/dataApi/createNote.js | 83 ++++++++++++++++++++++++ tests/dataApi/createNote.js | 88 ++++++++++++++++++++++++++ 2 files changed, 171 insertions(+) create mode 100644 browser/main/lib/dataApi/createNote.js create mode 100644 tests/dataApi/createNote.js diff --git a/browser/main/lib/dataApi/createNote.js b/browser/main/lib/dataApi/createNote.js new file mode 100644 index 00000000..5d984c49 --- /dev/null +++ b/browser/main/lib/dataApi/createNote.js @@ -0,0 +1,83 @@ +const sander = require('sander') +const resolveStorageData = require('./resolveStorageData') +const _ = require('lodash') +const keygen = require('browser/lib/keygen') +const path = require('path') +const CSON = require('season') + +function validateInput (input) { + if (!_.isArray(input.tags)) input.tags = [] + input.tags = input.tags.filter((tag) => _.isString(tag) && tag.trim().length > 0) + if (!_.isString(input.title)) input.title = '' + input.isStarred = !!input.isStarred + + switch (input.type) { + case 'MARKDOWN_NOTE': + if (!_.isString(input.content)) input.content = '' + break + case 'SNIPPET_NOTE': + if (!_.isString(input.description)) input.description = '' + if (!_.isArray(input.snippets)) { + input.snippets = [{ + name: '', + mode: 'text', + content: '' + }] + } + break + default: + throw new Error('Invalid type: only MARKDOWN_NOTE and SNIPPET_NOTE are available.') + } +} + +function createNote (storageKey, input) { + let targetStorage + try { + if (input == null) throw new Error('No input found.') + input = Object.assign({}, input) + validateInput(input) + + let cachedStorageList = JSON.parse(localStorage.getItem('storages')) + if (!_.isArray(cachedStorageList)) throw new Error('Target storage doesn\'t exist.') + + targetStorage = _.find(cachedStorageList, {key: storageKey}) + if (targetStorage == null) throw new Error('Target storage doesn\'t exist.') + } catch (e) { + return Promise.reject(e) + } + + return resolveStorageData(targetStorage) + .then(function checkFolderExists (storage) { + if (_.find(storage.folders, {key: input.folder}) == null) { + throw new Error('Target folder doesn\'t exist.') + } + return storage + }) + .then(function saveNote (storage) { + let key = keygen() + let isUnique = false + while (!isUnique) { + try { + sander.statSync(path.join(storage.path, 'notes', key + '.cson')) + } catch (err) { + if (err.code === 'ENOENT') { + isUnique = true + } else { + throw err + } + } + } + let noteData = Object.assign({}, input, { + key, + createdAt: new Date(), + updatedAt: new Date(), + storage: storageKey + }) + + CSON.writeFileSync(path.join(storage.path, 'notes', key + '.cson'), _.omit(noteData, ['key', 'storage'])) + + return noteData + }) +} + +module.exports = createNote diff --git a/tests/dataApi/createNote.js b/tests/dataApi/createNote.js new file mode 100644 index 00000000..74eb2940 --- /dev/null +++ b/tests/dataApi/createNote.js @@ -0,0 +1,88 @@ +const test = require('ava') +const createNote = require('browser/main/lib/dataApi/createNote') + +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 path = require('path') +const _ = require('lodash') +const TestDummy = require('../fixtures/TestDummy') +const sander = require('sander') +const os = require('os') +const CSON = require('season') +const faker = require('faker') + +const storagePath = path.join(os.tmpdir(), 'test/create-note') + +test.beforeEach((t) => { + t.context.storage = TestDummy.dummyStorage(storagePath) + localStorage.setItem('storages', JSON.stringify([t.context.storage.cache])) +}) + +test.serial('Create a note', (t) => { + const stoargeKey = t.context.storage.cache.key + const folderKey = t.context.storage.json.folders[0].key + + const input1 = { + type: 'SNIPPET_NOTE', + description: faker.lorem.lines(), + snippets: [{ + name: faker.system.fileName(), + mode: 'text', + content: faker.lorem.lines() + }], + tags: faker.lorem.words().split(' '), + folder: folderKey + } + input1.title = input1.description.split('\n').shift() + + const input2 = { + type: 'MARKDOWN_NOTE', + content: faker.lorem.lines(), + tags: faker.lorem.words().split(' '), + folder: folderKey + } + input2.title = input2.content.split('\n').shift() + + return Promise.resolve() + .then(function doTest () { + return Promise.all([ + createNote(stoargeKey, input1), + createNote(stoargeKey, input2) + ]) + }) + .then(function assert (data) { + let data1 = data[0] + let data2 = data[1] + + let jsonData1 = CSON.readFileSync(path.join(storagePath, 'notes', data1.key + '.cson')) + t.is(input1.title, data1.title) + t.is(input1.title, jsonData1.title) + t.is(input1.description, data1.description) + t.is(input1.description, jsonData1.description) + t.is(input1.tags.length, data1.tags.length) + t.is(input1.tags.length, jsonData1.tags.length) + t.is(input1.snippets.length, data1.snippets.length) + t.is(input1.snippets.length, jsonData1.snippets.length) + t.is(input1.snippets[0].content, data1.snippets[0].content) + t.is(input1.snippets[0].content, jsonData1.snippets[0].content) + t.is(input1.snippets[0].name, data1.snippets[0].name) + t.is(input1.snippets[0].name, jsonData1.snippets[0].name) + + let jsonData2 = CSON.readFileSync(path.join(storagePath, 'notes', data2.key + '.cson')) + t.is(input2.title, data2.title) + t.is(input2.title, jsonData2.title) + t.is(input2.content, data2.content) + t.is(input2.content, jsonData2.content) + t.is(input2.tags.length, data2.tags.length) + t.is(input2.tags.length, jsonData2.tags.length) + }) +}) + +test.after(function after () { + localStorage.clear() + sander.rimrafSync(storagePath) +})