Replace docquery to note-watcher, which supports lunr search index loading

NoteWatcher holds NoteCache, which caches recent notes and file modified time to help search index recovery.
This commit is contained in:
Seongjae Lee
2016-07-02 23:20:41 -07:00
parent 1f005a3025
commit f0b1fcd075
6 changed files with 606 additions and 14 deletions
+188
View File
@@ -0,0 +1,188 @@
fs = require 'fs'
path = require 'path'
temp = require 'temp'
NoteCache = require '../lib/note-cache'
temp.track()
String::repeat = (n) -> Array(n+1).join(this)
describe 'note cache', ->
cache = null
directoryPath = null
beforeEach ->
directoryPath = temp.mkdirSync()
fs.writeFileSync(path.join(directoryPath, 'foo.md'), 'foo'.repeat(100))
fs.utimesSync(path.join(directoryPath, 'foo.md'), 0, 1)
fs.writeFileSync(path.join(directoryPath, 'bar.md'), 'bar'.repeat(100))
fs.utimesSync(path.join(directoryPath, 'bar.md'), 0, 2)
fs.mkdirSync(path.join(directoryPath, 'baz'))
fs.writeFileSync(path.join(directoryPath, 'baz', 'baz.md'), 'baz'.repeat(100))
fs.utimesSync(path.join(directoryPath, 'baz', 'baz.md'), 0, 3)
cache = new NoteCache(directoryPath, 2, 100)
.upsert('foo.md', fs.statSync(path.join(directoryPath, 'foo.md')).mtime)
.upsert(path.join('baz', 'baz.md'), fs.statSync(path.join(directoryPath, 'baz/baz.md')).mtime)
.upsert('bar.md', fs.statSync(path.join(directoryPath, 'bar.md')).mtime)
.ready()
it 'getNoteIds', ->
noteIds = cache.getNoteIds()
for noteId in ['foo.md', 'bar.md', 'baz/baz.md']
expect(noteIds).toContain(noteId)
expect(cache.length()).toBe(3)
it 'getRecentNotes', ->
notes = cache.getRecentNotes()
expect(notes.length).toBe(2)
expect(notes[0].title).toBe('baz')
expect(notes[1].title).toBe('bar')
it 'getNote', ->
expect(cache.getNote('baz/baz.md').title).toBe('baz')
expect(cache.getNote('bar.md').title).toBe('bar')
expect(cache.getNote('foo.md').title).toBe('foo')
it 'hasNoteId', ->
expect(cache.hasNoteId('baz/baz.md')).toBe(true)
expect(cache.hasNoteId('bar.md')).toBe(true)
expect(cache.hasNoteId('foo.md')).toBe(true)
expect(cache.hasNoteId('baz.md')).toBe(false)
it 'getModifiedAt', ->
expect(cache.getModifiedAt('baz/baz.md')).toBe(3000)
expect(cache.getModifiedAt('bar.md')).toBe(2000)
expect(cache.getModifiedAt('foo.md')).toBe(1000)
it 'adds a new note', ->
fs.writeFileSync(path.join(directoryPath, 'moo.md'), 'moo'.repeat(100))
fs.utimesSync(path.join(directoryPath, 'moo.md'), 0, 4)
cache.upsert('moo.md', fs.statSync(path.join(directoryPath, 'moo.md')).mtime)
expect(cache.length()).toBe(4)
expect(cache.hasNoteId('moo.md')).toBe(true)
expect(cache.getModifiedAt('moo.md')).toBe(4000)
expect(cache.getRecentNotes().length).toBe(2)
expect(cache.getRecentNotes()[0].title).toBe('moo')
expect(cache.getNote('moo.md').title).toBe('moo')
it 'updates a note not in the recent notes', ->
fs.writeFileSync(path.join(directoryPath, 'foo.md'), 'foo'.repeat(2))
fs.utimesSync(path.join(directoryPath, 'foo.md'), 0, 4)
cache.upsert('foo.md', fs.statSync(path.join(directoryPath, 'foo.md')).mtime)
expect(cache.length()).toBe(3)
expect(cache.hasNoteId('foo.md')).toBe(true)
expect(cache.getModifiedAt('foo.md')).toBe(4000)
expect(cache.getRecentNotes().length).toBe(2)
expect(cache.getRecentNotes()[0].title).toBe('foo')
expect(cache.getNote('foo.md').title).toBe('foo')
it 'updates a note in the recent notes', ->
fs.writeFileSync(path.join(directoryPath, 'bar.md'), 'bar'.repeat(2))
fs.utimesSync(path.join(directoryPath, 'bar.md'), 0, 4)
cache.upsert('bar.md', fs.statSync(path.join(directoryPath, 'bar.md')).mtime)
expect(cache.length()).toBe(3)
expect(cache.hasNoteId('bar.md')).toBe(true)
expect(cache.getModifiedAt('bar.md')).toBe(4000)
expect(cache.getRecentNotes().length).toBe(2)
expect(cache.getRecentNotes()[0].title).toBe('bar')
expect(cache.getNote('bar.md').title).toBe('bar')
it 'deletes a note not in the recent notes', ->
fs.unlinkSync(path.join(directoryPath, 'foo.md'))
cache.remove('foo.md')
expect(cache.length()).toBe(2)
expect(cache.hasNoteId('foo.md')).toBe(false)
expect(cache.getRecentNotes().length).toBe(2)
expect(cache.getRecentNotes()[0].title).toBe('baz')
expect(cache.getRecentNotes()[1].title).toBe('bar')
it 'deletes a note in the recent notes', ->
cache.remove('bar.md')
expect(cache.length()).toBe(2)
expect(cache.hasNoteId('bar.md')).toBe(false)
expect(cache.getRecentNotes().length).toBe(2)
expect(cache.getRecentNotes()[0].title).toBe('baz')
expect(cache.getRecentNotes()[1].title).toBe('foo')
it 'deletes two notes', ->
cache.remove('bar.md')
cache.remove('foo.md')
expect(cache.length()).toBe(1)
expect(cache.hasNoteId('foo.md')).toBe(false)
expect(cache.hasNoteId('bar.md')).toBe(false)
expect(cache.getRecentNotes().length).toBe(1)
expect(cache.getRecentNotes()[0].title).toBe('baz')
# describe 'note cache', ->
# cache = null
# directoryPath = null
#
# beforeEach ->
# directoryPath = temp.mkdirSync()
#
# it 'handles cyclic symlink directories', ->
# fs.symlinkSync(directoryPath, path.join(directoryPath, 'foo'))
# fs.writeFileSync(path.join(directoryPath, 'foo.md'), 'foo'.repeat(100))
# cache = new NoteCache(directoryPath, ['.md'], 2, 100)
# expect(cache.length()).toBe(1)
#
# it 'handles symlink notes', ->
# # TODO: this behavior should be same for chokidar.
# anotherDirectoryPath = temp.mkdirSync()
# fs.writeFileSync(path.join(anotherDirectoryPath, 'foo.md'), 'foo'.repeat(100))
# fs.symlinkSync(path.join(anotherDirectoryPath, 'foo.md'), path.join(directoryPath, 'foo.md'))
# fs.symlinkSync(path.join(anotherDirectoryPath, 'foo.md'), path.join(directoryPath, 'bar.md'))
# fs.symlinkSync(anotherDirectoryPath, path.join(directoryPath, 'bar'))
# cache = new NoteCache(directoryPath, ['.md'], 2, 100)
# # foo.md, bar.md, bar/foo.md
# expect(cache.length()).toBe(3)
describe 'note cache', ->
cache = null
directoryPath = null
beforeEach ->
directoryPath = temp.mkdirSync()
cache = new NoteCache(directoryPath, 2, 100)
.ready()
fs.writeFileSync(path.join(directoryPath, 'foo.md'), 'foo'.repeat(100))
fs.utimesSync(path.join(directoryPath, 'foo.md'), 0, 1)
fs.writeFileSync(path.join(directoryPath, 'bar.md'), 'bar'.repeat(100))
fs.utimesSync(path.join(directoryPath, 'bar.md'), 0, 2)
fs.mkdirSync(path.join(directoryPath, 'baz'))
fs.writeFileSync(path.join(directoryPath, 'baz', 'baz.md'), 'baz'.repeat(100))
fs.utimesSync(path.join(directoryPath, 'baz', 'baz.md'), 0, 3)
cache
.upsert('foo.md', fs.statSync(path.join(directoryPath, 'foo.md')).mtime)
.upsert('bar.md', fs.statSync(path.join(directoryPath, 'bar.md')).mtime)
.upsert(path.join('baz', 'baz.md'), fs.statSync(path.join(directoryPath, 'baz', 'baz.md')).mtime)
it 'has all note ids', ->
noteIds = cache.getNoteIds()
for noteId in ['foo.md', 'bar.md', 'baz/baz.md']
expect(noteIds).toContain(noteId)
expect(cache.length()).toBe(3)
it 'getRecentNotes', ->
notes = cache.getRecentNotes()
expect(notes.length).toBe(2)
expect(notes[0].title).toBe('baz')
expect(notes[1].title).toBe('bar')
it 'getNote', ->
expect(cache.getNote('baz/baz.md').title).toBe('baz')
expect(cache.getNote('bar.md').title).toBe('bar')
expect(cache.getNote('foo.md').title).toBe('foo')
it 'getModifiedAt', ->
expect(cache.getModifiedAt('baz/baz.md')).toBe(3000)
expect(cache.getModifiedAt('bar.md')).toBe(2000)
expect(cache.getModifiedAt('foo.md')).toBe(1000)
+143
View File
@@ -0,0 +1,143 @@
fs = require 'fs'
path = require 'path'
temp = require 'temp'
NoteWatcher = require '../lib/note-watcher'
temp.track()
describe 'note-watcher', ->
watcher = null
directoryPath = null
beforeEach ->
directoryPath = temp.mkdirSync()
fs.writeFileSync(
path.join(directoryPath, 'foo.md'),
'The use of foo in a programming context is generally credited to the Tech Model Railroad Club (TMRC) of MIT.')
fs.writeFileSync(
path.join(directoryPath, 'bar.md'),
'When used in connection with bar it is generally traced to the World War II military slang FUBAR.')
spy = jasmine.createSpy()
watcher = new NoteWatcher(directoryPath)
watcher.on 'ready', spy
waitsFor -> spy.wasCalled
afterEach ->
watcher.close()
# it 'handles a symbolic link note properly', ->
# spy = jasmine.createSpy()
# watcher.on 'update', spy
#
# anotherDirectoryPath = temp.mkdirSync()
# fs.writeFileSync(path.join(anotherDirectoryPath, 'baz.md'), 'A common name for the foobar, also foobaz.')
# fs.symlinkSync(path.join(anotherDirectoryPath, 'baz.md'), path.join(directoryPath, 'baz.md'))
#
# waitsFor -> spy.wasCalled
#
# runs ->
# result = watcher.search('baz')
# expect(result.length).toBe(1)
# it 'handles a symbolic link directory properly', ->
# spy = jasmine.createSpy()
# watcher.on 'update', spy
#
# anotherDirectoryPath = temp.mkdirSync()
# fs.writeFileSync(path.join(anotherDirectoryPath, 'baz.md'), 'A common name for the foobar, also foobaz.')
# fs.symlinkSync(anotherDirectoryPath, path.join(directoryPath, 'baz'))
#
# waitsFor -> spy.wasCalled
#
# runs ->
# result = watcher.search('baz')
# expect(result.length).toBe(1)
# expect(result[0].filePath).toBe(path.join(directoryPath, 'baz', 'baz.md'))
# it 'handles paired symbolic links properly without falling into an infinite loop', ->
# spy = jasmine.createSpy()
# watcher.on 'update', spy
#
# anotherDirectoryPath = temp.mkdirSync()
# fs.writeFileSync(path.join(anotherDirectoryPath, 'baz.md'), 'A common name for the foobar, also foobaz.')
# fs.symlinkSync(anotherDirectoryPath, path.join(directoryPath, 'bazDir'))
# fs.symlinkSync(directoryPath, path.join(anotherDirectoryPath, 'fooDir'))
#
# waitsFor -> spy.wasCalled
#
# runs ->
# result = watcher.search('baz')
# expect(result.length).toBe(1)
# expect(result[0].filePath).toBe(path.join(directoryPath, 'bazDir', 'baz.md'))
# it 'watches adding a file', ->
# spy = jasmine.createSpy()
# watcher.on 'update', spy
# fs.writeFileSync(path.join(directoryPath, 'note.md'), 'hello world')
#
# waitsFor -> spy.wasCalled
#
# it 'watches changing a file', ->
# spy = jasmine.createSpy()
# watcher.on 'update', spy
# filePath = path.join(directoryPath, 'note.md')
# fs.writeFileSync(filePath, 'hello world')
# waitsFor -> spy.callCount == 1
#
# runs -> fs.writeFileSync(filePath, 'hello world 2')
#
# waitsFor -> spy.callCount == 2
#
# it 'watches removing a file', ->
# spy = jasmine.createSpy()
# watcher.on('update', spy)
# filePath = path.join(directoryPath, 'note.md')
# fs.writeFileSync(filePath, 'hello world')
# waitsFor -> spy.callCount == 1
#
# runs -> fs.unlinkSync(filePath)
#
# waitsFor -> spy.callCount == 2
#
# it 'searches', ->
# result = watcher.search('programming')
# expect(result.length).toBe(1)
# expect(result[0].title).toBe('foo')
#
# it 'saves and loads', ->
# watcher.save()
# watcher.close()
# watcher = new NoteWatcher(directoryPath)
# spy = jasmine.createSpy()
# watcher.on 'ready', spy
#
# waitsFor -> spy.wasCalled
#
# runs ->
# result = watcher.search('programming')
# expect(result.length).toBe(1)
# expect(result[0].title).toBe('foo')
it 'loads the modified contents correctly', ->
watcher.save()
watcher.close()
# create, change, and delete
fs.writeFileSync(path.join(directoryPath, 'baz.md'), 'A common name for the foobar, also foobaz.')
fs.writeFileSync(path.join(directoryPath, 'foo.md'), 'The etymology of foo is obscure.')
fs.unlinkSync(path.join(directoryPath, 'bar.md'))
watcher = new NoteWatcher(directoryPath)
spy = jasmine.createSpy()
watcher.on('ready', spy)
waitsFor -> spy.wasCalled
runs ->
# in deleted foo.md
expect(watcher.search('programming').length).toBe(0)
# in replaced foo.md
expect(watcher.search('obscure').length).toBe(1)
# in bar.md
expect(watcher.search('connection').length).toBe(0)
# in baz.md
expect(watcher.search('baz').length).toBe(1)