Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 107 additions & 1 deletion src/lib/db/store.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createDbStoreCreator, getStorageDataList } from './store'
import { MemoryLiteStorage } from 'ltstrg'
import { renderHook, act } from '@testing-library/react-hooks'
import { NoteStorage } from './types'
import { NoteStorage, NoteDoc } from './types'
import { getFolderId } from './utils'
import { RouterProvider } from '../router'

Expand Down Expand Up @@ -201,4 +201,110 @@ describe('DbStore', () => {

// TODO: routing test when current folder or current folder's parent folder is deleted.
})

describe('#createNote', () => {
it('creates a note and registers in the map', async () => {
// Given
const { result } = prepareDbStore()
let storage: NoteStorage
let noteDoc: NoteDoc | undefined
await act(async () => {
await result.current.initialize()
storage = await result.current.createStorage('test')
await result.current.createFolder(storage.id, '/test')

// When
noteDoc = await result.current.createNote(storage.id, {
title: 'testNote'
})
})

// Then
expect(result.current.storageMap[storage!.id]!.noteMap).toEqual({
[noteDoc!._id]: expect.objectContaining({ title: 'testNote' })
})
})

it('creates a note and register its tag', async () => {
// Given
const { result } = prepareDbStore()
let storage: NoteStorage
let noteDoc: NoteDoc | undefined
await act(async () => {
await result.current.initialize()
storage = await result.current.createStorage('test')
await result.current.createFolder(storage.id, '/test')

// When
noteDoc = await result.current.createNote(storage.id, {
title: 'testNote',
tags: ['testTag']
})
})

// Then
expect(
result.current.storageMap[storage!.id]!.tagMap[noteDoc!.tags[0]]!
.noteIdSet
).toMatchObject(new Set([noteDoc!._id]))
})
})

describe('#updateNote', () => {
it('update a Note and handle tag removal', async () => {
// Given
const { result } = prepareDbStore()
let storage: NoteStorage
let noteDoc: NoteDoc | undefined
await act(async () => {
await result.current.initialize()
storage = await result.current.createStorage('test')
await result.current.createFolder(storage.id, '/test')
noteDoc = await result.current.createNote(storage.id, {
title: 'testNote',
tags: ['tag1', 'tag2']
})

// When
noteDoc = await result.current.updateNote(storage.id, noteDoc!._id, {
tags: ['tag2']
})
})

// Then
expect(
result.current.storageMap[storage!.id]!.tagMap['tag1']!.noteIdSet.size
).toEqual(0)
})

it('update a Note and handle tag addition', async () => {
// Given
const { result } = prepareDbStore()
let storage: NoteStorage
let noteDoc: NoteDoc | undefined
await act(async () => {
await result.current.initialize()
storage = await result.current.createStorage('test')
await result.current.createFolder(storage.id, '/test')
noteDoc = await result.current.createNote(storage.id, {
title: 'testNote',
tags: ['tag1']
})
await result.current.createNote(storage.id, {
title: 'testNote',
tags: ['tag2']
})

// When
noteDoc = await result.current.updateNote(storage.id, noteDoc!._id, {
tags: ['tag1', 'tag2']
})
})

// Then
expect(
result.current.storageMap[storage!.id]!.tagMap['tag2']!.noteIdSet.size
).toEqual(2)
})
})
})
75 changes: 71 additions & 4 deletions src/lib/db/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import {
ObjectMap,
NoteDoc,
NoteDocEditibleProps,
PopulatedFolderDoc
PopulatedFolderDoc,
PopulatedTagDoc
} from './types'
import { useState, useCallback } from 'react'
import { createStoreContext } from '../utils/context'
Expand All @@ -23,6 +24,8 @@ import { produce } from 'immer'
import { useRouter } from '../router'
import { values } from '../db/utils'
import { storageDataListKey } from '../localStorageKeys'
import { TAG_ID_PREFIX } from './consts'
import { difference } from 'ramda'

export interface DbStore {
initialized: boolean
Expand Down Expand Up @@ -213,6 +216,7 @@ export function createDbStoreCreator(
parentFolderPathnamesToCheck
)
: []

const folder: PopulatedFolderDoc =
storage.folderMap[noteDoc.folderPathname] == null
? ({
Expand All @@ -228,7 +232,28 @@ export function createDbStoreCreator(
])
}

// TODO: Reflect tags
const modifiedTags = ((await Promise.all(
noteDoc.tags.map(async tag => {
if (storage.tagMap[tag] == null) {
return {
...(await storage.db.getTag(tag)!),
noteIdSet: new Set([noteDoc._id])
} as PopulatedTagDoc
} else {
return {
...storage.tagMap[tag]!,
noteIdSet: new Set([
...storage.tagMap[tag]!.noteIdSet.values(),
noteDoc._id
])
}
}
})
)) as PopulatedTagDoc[]).reduce((acc, tag) => {
acc[tag._id.replace(TAG_ID_PREFIX, '')] = tag
return acc
}, {})

setStorageMap(
produce((draft: ObjectMap<NoteStorage>) => {
draft[storageId]!.noteMap[noteDoc._id] = noteDoc
Expand All @@ -241,9 +266,12 @@ export function createDbStoreCreator(
}
})
draft[storageId]!.folderMap[noteDoc.folderPathname] = folder
draft[storageId]!.tagMap = {
...storage.tagMap,
...modifiedTags
}
})
)

return noteDoc
},
[storageMap]
Expand Down Expand Up @@ -288,7 +316,41 @@ export function createDbStoreCreator(
])
}

// TODO: Reflect tags
const removedTags: ObjectMap<PopulatedTagDoc> = difference(
storage.noteMap[noteDoc._id]!.tags,
noteDoc.tags
).reduce((acc, tag) => {
const newNoteIdSet = new Set(storage.tagMap[tag]!.noteIdSet)
newNoteIdSet.delete(noteDoc._id)
acc[tag] = {
...storage.tagMap[tag]!,
noteIdSet: newNoteIdSet
}
return acc
}, {})

const modifiedTags: ObjectMap<PopulatedTagDoc> = ((await Promise.all(
noteDoc.tags.map(async tag => {
if (storage.tagMap[tag] == null) {
return {
...(await storage.db.getTag(tag)!),
noteIdSet: new Set([noteDoc._id])
} as PopulatedTagDoc
} else {
return {
...storage.tagMap[tag]!,
noteIdSet: new Set([
...storage.tagMap[tag]!.noteIdSet.values(),
noteDoc._id
])
}
}
})
)) as PopulatedTagDoc[]).reduce((acc, tag) => {
acc[tag._id.replace(TAG_ID_PREFIX, '')] = tag
return acc
}, {})

setStorageMap(
produce((draft: ObjectMap<NoteStorage>) => {
draft[storageId]!.noteMap[noteDoc._id] = noteDoc
Expand All @@ -301,6 +363,11 @@ export function createDbStoreCreator(
}
})
draft[storageId]!.folderMap[noteDoc.folderPathname] = folder
draft[storageId]!.tagMap = {
...storage.tagMap,
...removedTags,
...modifiedTags
}
})
)

Expand Down
5 changes: 4 additions & 1 deletion webpack.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ import ErrorOverlayPlugin from 'error-overlay-webpack-plugin'
import dotenv from 'dotenv'
import CopyPlugin from 'copy-webpack-plugin'

const { parsed } = dotenv.config()
let { parsed } = dotenv.config()
if (parsed == null) {
parsed = {}
}

module.exports = {
entry: [
Expand Down