diff --git a/packages/core/__e2e__/monographs.test.js b/packages/core/__e2e__/monographs.test.js index 82447afe5..0509e6b1d 100644 --- a/packages/core/__e2e__/monographs.test.js +++ b/packages/core/__e2e__/monographs.test.js @@ -17,25 +17,22 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { databaseTest, noteTest, StorageInterface } from "../__tests__/utils"; -import { login } from "./utils"; -import { test, expect, beforeEach, afterAll } from "vitest"; +import { databaseTest, noteTest } from "../__tests__/utils"; +import { login, logout } from "./utils"; +import { test, expect, afterAll } from "vitest"; const TEST_TIMEOUT = 30 * 1000; -beforeEach(() => { - StorageInterface.clear(); -}); - afterAll(async () => { const db = await databaseTest(); + await login(db); await db.monographs.init(); for (const id of db.monographs.monographs) { await db.monographs.unpublish(id); } - StorageInterface.clear(); + await logout(db); }, TEST_TIMEOUT); // test("get monographs", () => @@ -62,6 +59,8 @@ test( const note = db.notes.note(id); expect(monograph.id).toBe(monographId); expect(monograph.title).toBe(note.title); + + await logout(db); }), TEST_TIMEOUT ); @@ -83,6 +82,8 @@ test( await db.monographs.publish(id); monograph = await db.monographs.get(monographId); expect(monograph.title).toBe(editedTitle); + + await logout(db); }), TEST_TIMEOUT ); @@ -99,6 +100,8 @@ test( await db.monographs.unpublish(id); expect(db.monographs.all.find((m) => m.id === id)).toBeUndefined(); + + await logout(db); }), TEST_TIMEOUT ); diff --git a/packages/core/__e2e__/token-manager.test.js b/packages/core/__e2e__/token-manager.test.js index 112a6dfd2..75ebdf650 100644 --- a/packages/core/__e2e__/token-manager.test.js +++ b/packages/core/__e2e__/token-manager.test.js @@ -17,42 +17,43 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import DB from "../src/api"; -import StorageInterface from "../__mocks__/storage.mock"; +import { databaseTest } from "../__tests__/utils"; import { login } from "./utils"; import { test, expect } from "vitest"; -test("refresh token concurrently", async () => { - const db = new DB(); - db.setup(StorageInterface); - await db.init(); +test( + "refresh token concurrently", + async () => + databaseTest().then(async (db) => { + await expect(login(db)).resolves.not.toThrow(); - await expect(login(db)).resolves.not.toThrow(); + const token = await db.user.tokenManager.getToken(); + expect(token).toBeDefined(); - const token = await db.user.tokenManager.getToken(); - expect(token).toBeDefined(); + expect( + await Promise.all([ + db.user.tokenManager._refreshToken(true), + db.user.tokenManager._refreshToken(true), + db.user.tokenManager._refreshToken(true), + db.user.tokenManager._refreshToken(true) + ]) + ).toHaveLength(4); + }), + 30000 +); - expect( - await Promise.all([ - db.user.tokenManager._refreshToken(true), - db.user.tokenManager._refreshToken(true), - db.user.tokenManager._refreshToken(true), - db.user.tokenManager._refreshToken(true) - ]) - ).toHaveLength(4); -}, 30000); +test( + "refresh token using the same refresh_token multiple time", + async () => + databaseTest().then(async (db) => { + await expect(login(db)).resolves.not.toThrow(); -test("refresh token using the same refresh_token multiple time", async () => { - const db = new DB(); - db.setup(StorageInterface); - await db.init(); - - await expect(login(db)).resolves.not.toThrow(); - - const token = await db.user.tokenManager.getToken(); - expect(token).toBeDefined(); - for (let i = 0; i <= 5; ++i) { - await db.user.tokenManager._refreshToken(true); - await db.user.tokenManager.saveToken(token); - } -}, 30000); + const token = await db.user.tokenManager.getToken(); + expect(token).toBeDefined(); + for (let i = 0; i <= 5; ++i) { + await db.user.tokenManager._refreshToken(true); + await db.user.tokenManager.saveToken(token); + } + }), + 30000 +); diff --git a/packages/core/__e2e__/utils.js b/packages/core/__e2e__/utils.js index 6fbabf8ed..279ffc305 100644 --- a/packages/core/__e2e__/utils.js +++ b/packages/core/__e2e__/utils.js @@ -34,3 +34,7 @@ export async function login(db) { await db.user.authenticatePassword(user.email, user.password, user.hashed); } + +export async function logout(db) { + await db.user.logout(true); +} diff --git a/packages/core/__mocks__/storage.mock.js b/packages/core/__mocks__/storage.mock.js deleted file mode 100644 index e649fe1f4..000000000 --- a/packages/core/__mocks__/storage.mock.js +++ /dev/null @@ -1,102 +0,0 @@ -/* -This file is part of the Notesnook project (https://notesnook.com/) - -Copyright (C) 2023 Streetwriters (Private) Limited - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with this program. If not, see . -*/ - -var storage = {}; - -async function read(key) { - return new Promise((resolve) => resolve(storage[key])); -} - -async function readMulti(keys) { - return new Promise((resolve) => { - const result = []; - keys.forEach((key) => { - result.push([key, storage[key]]); - }); - resolve(result); - }); -} - -async function write(key, data) { - return new Promise((resolve) => resolve((storage[key] = data))); -} -function remove(key) { - delete storage[key]; -} -function clear() { - storage = {}; -} -function getAllKeys() { - return Object.keys(storage); -} - -function encrypt(password, data) { - return new Promise((resolve, reject) => { - if (typeof data === "object") reject("data cannot be object."); - resolve({ - iv: "some iv", - cipher: data, - salt: "i am some salt", - length: data.length, - key: password - }); - }); -} - -function decrypt(key, data) { - if ( - !key || - !data.key || - key.password === data.key.password || - key.key.password === data.key.password - ) - return Promise.resolve(data.cipher); - else throw new Error("Wrong password"); -} - -async function deriveCryptoKey(name, data) { - storage[name] = { key: data.password, salt: "salt" }; -} - -async function getCryptoKey(name) { - return storage[name].key; -} - -async function hash(password) { - return password; -} - -async function generateCryptoKey(password, salt) { - return { password, salt }; -} - -module.exports = { - read, - readMulti, - write, - remove, - clear, - encrypt, - decrypt, - deriveCryptoKey, - generateCryptoKey, - getCryptoKey, - getAllKeys, - hash -}; diff --git a/packages/core/__tests__/backup.test.js b/packages/core/__tests__/backup.test.js index 2782af79e..1d4b3c177 100644 --- a/packages/core/__tests__/backup.test.js +++ b/packages/core/__tests__/backup.test.js @@ -18,8 +18,9 @@ along with this program. If not, see . */ import { - StorageInterface, + TEST_NOTE, databaseTest, + loginFakeUser, noteTest, notebookTest } from "./utils"; @@ -27,11 +28,7 @@ import v52Backup from "./__fixtures__/backup.v5.2.json"; import v52BackupCopy from "./__fixtures__/backup.v5.2.copy.json"; import v56BackupCopy from "./__fixtures__/backup.v5.6.json"; import qclone from "qclone"; -import { beforeEach, test, expect, describe } from "vitest"; - -beforeEach(() => { - StorageInterface.clear(); -}); +import { test, expect, describe } from "vitest"; test("export backup", () => noteTest().then(() => @@ -44,46 +41,44 @@ test("export backup", () => )); test("export encrypted backup", () => - noteTest().then(() => - notebookTest().then(async ({ db }) => { - const exp = await db.backup.export("node", true); - let backup = JSON.parse(exp); - expect(backup.type).toBe("node"); - expect(backup.date).toBeGreaterThan(0); - expect(backup.data.iv).toBe("some iv"); - }) - )); + notebookTest().then(async ({ db }) => { + await loginFakeUser(db); + await db.notes.add(TEST_NOTE); + const exp = await db.backup.export("node", true); + let backup = JSON.parse(exp); + expect(backup.type).toBe("node"); + expect(backup.date).toBeGreaterThan(0); + expect(backup.data.iv).not.toBeUndefined(); + })); test("import backup", () => - noteTest().then(() => - notebookTest().then(async ({ db, id }) => { - const exp = await db.backup.export("node"); - StorageInterface.clear(); - await db.backup.import(JSON.parse(exp)); - expect(db.notebooks.notebook(id).data.id).toBe(id); - }) - )); + notebookTest().then(async ({ db, id }) => { + await db.notes.add(TEST_NOTE); + const exp = await db.backup.export("node"); + await db.storage.clear(); + await db.backup.import(JSON.parse(exp)); + expect(db.notebooks.notebook(id).data.id).toBe(id); + })); test("import encrypted backup", () => - noteTest().then(() => - notebookTest().then(async ({ db, id }) => { - const exp = await db.backup.export("node", true); - StorageInterface.clear(); - await db.backup.import(JSON.parse(exp), "password"); - expect(db.notebooks.notebook(id).data.id).toBe(id); - }) - )); + notebookTest().then(async ({ db, id }) => { + await loginFakeUser(db); + await db.notes.add(TEST_NOTE); + const exp = await db.backup.export("node", true); + await db.storage.clear(); + await db.backup.import(JSON.parse(exp), "password"); + expect(db.notebooks.notebook(id).data.id).toBe(id); + })); test("import tempered backup", () => - noteTest().then(() => - notebookTest().then(async ({ db }) => { - const exp = await db.backup.export("node"); - StorageInterface.clear(); - const backup = JSON.parse(exp); - backup.data.hello = "world"; - await expect(db.backup.import(backup)).rejects.toThrow(/tempered/); - }) - )); + notebookTest().then(async ({ db }) => { + await db.notes.add(TEST_NOTE); + const exp = await db.backup.export("node"); + await db.storage.clear(); + const backup = JSON.parse(exp); + backup.data.hello = "world"; + await expect(db.backup.import(backup)).rejects.toThrow(/tempered/); + })); describe.each([ ["v5.2", v52Backup], diff --git a/packages/core/__tests__/content.test.js b/packages/core/__tests__/content.test.js index 76823de8e..5322be31c 100644 --- a/packages/core/__tests__/content.test.js +++ b/packages/core/__tests__/content.test.js @@ -17,12 +17,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { StorageInterface, databaseTest } from "./utils"; -import { beforeEach, test, expect } from "vitest"; - -beforeEach(() => { - StorageInterface.clear(); -}); +import { databaseTest } from "./utils"; +import { test, expect } from "vitest"; test("adding a deleted content should not throw", () => databaseTest().then(async (db) => { diff --git a/packages/core/__tests__/db.test.js b/packages/core/__tests__/db.test.js index 58a8b2d86..dcd47991d 100644 --- a/packages/core/__tests__/db.test.js +++ b/packages/core/__tests__/db.test.js @@ -17,14 +17,12 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import DB from "../src/api"; import Constants from "../src/utils/constants"; -import StorageInterface from "../__mocks__/storage.mock"; import { test, expect } from "vitest"; +import { databaseTest } from "./utils"; -test("db.host should change HOST", () => { - const db = new DB(); - db.setup(StorageInterface); - db.host({ API_HOST: "hello world" }); - expect(Constants.API_HOST).toBe("hello world"); -}); +test("db.host should change HOST", () => + databaseTest().then((db) => { + db.host({ API_HOST: "hello world" }); + expect(Constants.API_HOST).toBe("hello world"); + })); diff --git a/packages/core/__tests__/lookup.test.js b/packages/core/__tests__/lookup.test.js index 2bc1db8f5..422c7a964 100644 --- a/packages/core/__tests__/lookup.test.js +++ b/packages/core/__tests__/lookup.test.js @@ -17,18 +17,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { - StorageInterface, - noteTest, - TEST_NOTE, - notebookTest, - TEST_NOTEBOOK2 -} from "./utils"; -import { beforeEach, test, expect } from "vitest"; - -beforeEach(async () => { - StorageInterface.clear(); -}); +import { noteTest, TEST_NOTE, notebookTest, TEST_NOTEBOOK2 } from "./utils"; +import { test, expect } from "vitest"; const content = { ...TEST_NOTE.content, diff --git a/packages/core/__tests__/note-history.test.js b/packages/core/__tests__/note-history.test.js index 1430100d3..20e692352 100644 --- a/packages/core/__tests__/note-history.test.js +++ b/packages/core/__tests__/note-history.test.js @@ -17,12 +17,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { delay, noteTest, StorageInterface, TEST_NOTE } from "./utils"; -import { beforeEach, test, expect } from "vitest"; - -beforeEach(async () => { - StorageInterface.clear(); -}); +import { delay, noteTest, TEST_NOTE } from "./utils"; +import { test, expect } from "vitest"; // async function sessionTest(db, noteId) { // let note = await db.notes.note(noteId).data; diff --git a/packages/core/__tests__/notebooks.test.js b/packages/core/__tests__/notebooks.test.js index 46c82efd3..8ae6eaf6a 100644 --- a/packages/core/__tests__/notebooks.test.js +++ b/packages/core/__tests__/notebooks.test.js @@ -17,19 +17,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { - StorageInterface, - notebookTest, - TEST_NOTEBOOK, - TEST_NOTE, - delay -} from "./utils"; +import { notebookTest, TEST_NOTEBOOK, TEST_NOTE, delay } from "./utils"; import { makeTopic } from "../src/collections/topics"; -import { beforeEach, test, expect } from "vitest"; - -beforeEach(async () => { - StorageInterface.clear(); -}); +import { test, expect } from "vitest"; test("add a notebook", () => notebookTest().then(({ db, id }) => { @@ -153,7 +143,7 @@ test("merge notebook with topic removed that is edited in the local notebook", ( const newNotebook = { ...notebook.data, remote: true }; newNotebook.topics.splice(0, 1); // remove hello topic - await StorageInterface.write("lastSynced", Date.now()); + await db.storage.write("lastSynced", Date.now()); await delay(500); diff --git a/packages/core/__tests__/notes.test.js b/packages/core/__tests__/notes.test.js index 89d8a4056..e2a7cb1bd 100644 --- a/packages/core/__tests__/notes.test.js +++ b/packages/core/__tests__/notes.test.js @@ -19,19 +19,15 @@ along with this program. If not, see . import { groupArray } from "../src/utils/grouping"; import { - StorageInterface, databaseTest, noteTest, groupedTest, TEST_NOTE, TEST_NOTEBOOK, - IMG_CONTENT + IMG_CONTENT, + loginFakeUser } from "./utils"; -import { beforeEach, test, expect } from "vitest"; - -beforeEach(async () => { - StorageInterface.clear(); -}); +import { test, expect } from "vitest"; test("add invalid note", () => databaseTest().then(async (db) => { @@ -314,40 +310,12 @@ test("grouping items where item.title is empty or undefined shouldn't throw", () test("note content should not contain image base64 data after save", () => noteTest().then(async ({ db, id }) => { - StorageInterface.write(`_uk_@email@email.com`, { - key: { password: "password" } - }); - - await db.user.setUser({ - email: "email@email.com", - attachmentsKey: { - cipher: "{}", - iv: "iv", - salt: "salt", - length: 100, - key: { password: "password" } - } - }); - - await db.attachments.add( - { - iv: "iv", - length: 100, - alg: "xha-stream", - hash: "d3eab72e94e3cd35", - hashType: "xxh64", - type: "image/jpeg", - chunkSize: 512, - filename: "hello", - key: {}, - salt: "hellowrold" - }, - id - ); + await loginFakeUser(db); await db.notes.add({ id, content: { type: "tiptap", data: IMG_CONTENT } }); const note = db.notes.note(id); const content = await note.content(); + expect(content).not.toContain(`src="data:image/png;`); expect(content).not.toContain(`src=`); })); diff --git a/packages/core/__tests__/settings.test.js b/packages/core/__tests__/settings.test.js index b76b67893..fbb22fae1 100644 --- a/packages/core/__tests__/settings.test.js +++ b/packages/core/__tests__/settings.test.js @@ -17,12 +17,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { databaseTest, StorageInterface } from "./utils"; -import { beforeEach, test, expect } from "vitest"; - -beforeEach(() => { - StorageInterface.clear(); -}); +import { databaseTest } from "./utils"; +import { test, expect } from "vitest"; test("settings' dateModified should not update on init", () => databaseTest().then(async (db) => { diff --git a/packages/core/__tests__/shortcuts.test.js b/packages/core/__tests__/shortcuts.test.js index 735f84904..749737f88 100644 --- a/packages/core/__tests__/shortcuts.test.js +++ b/packages/core/__tests__/shortcuts.test.js @@ -17,12 +17,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { databaseTest, notebookTest, StorageInterface } from "./utils"; -import { beforeEach, test, expect } from "vitest"; - -beforeEach(() => { - StorageInterface.clear(); -}); +import { databaseTest, notebookTest } from "./utils"; +import { test, expect } from "vitest"; test("create a shortcut of an invalid item should throw", () => databaseTest().then(async (db) => { diff --git a/packages/core/__tests__/storage.test.js b/packages/core/__tests__/storage.test.js index 8bb2adff3..8d18c734b 100644 --- a/packages/core/__tests__/storage.test.js +++ b/packages/core/__tests__/storage.test.js @@ -17,26 +17,35 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import StorageInterface from "../__mocks__/storage.mock"; +import { NodeStorageInterface } from "../__mocks__/node-storage.mock"; import Storage from "../src/database/storage"; import { test, expect } from "vitest"; -const storage = new Storage(StorageInterface); test("add a value", async () => { + const storage = new Storage(new NodeStorageInterface()); await storage.write("hello", "world"); + let value = await storage.read("hello"); + expect(value).toBe("world"); }); test("remove", async () => { + const storage = new Storage(new NodeStorageInterface()); + await storage.write("hello", "world"); await storage.remove("hello"); + let value = await storage.read("hello"); + expect(value).toBeUndefined(); }); test("clear", async () => { + const storage = new Storage(new NodeStorageInterface()); await storage.write("hello", "world"); storage.clear(); + let value = await storage.read("hello"); + expect(value).toBeUndefined(); }); diff --git a/packages/core/__tests__/tags.test.js b/packages/core/__tests__/tags.test.js index 5c78cc624..5fcdb562c 100644 --- a/packages/core/__tests__/tags.test.js +++ b/packages/core/__tests__/tags.test.js @@ -17,12 +17,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { noteTest, TEST_NOTE, StorageInterface } from "./utils"; -import { beforeEach, test, expect, describe } from "vitest"; - -beforeEach(async () => { - StorageInterface.clear(); -}); +import { noteTest, TEST_NOTE } from "./utils"; +import { test, expect, describe } from "vitest"; function checkColorValue(note, value) { expect(note.data.color).toBe(value); diff --git a/packages/core/__tests__/topics.test.js b/packages/core/__tests__/topics.test.js index 17963e341..5898c41ce 100644 --- a/packages/core/__tests__/topics.test.js +++ b/packages/core/__tests__/topics.test.js @@ -17,16 +17,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { - delay, - notebookTest, - noteTest, - StorageInterface, - TEST_NOTE -} from "./utils"; -import { beforeEach, test, expect } from "vitest"; - -beforeEach(() => StorageInterface.clear()); +import { delay, notebookTest, TEST_NOTE } from "./utils"; +import { test, expect } from "vitest"; test("get empty topic", () => notebookTest().then(({ db, id }) => { @@ -133,16 +125,15 @@ test("delete a topic", () => })); test("delete note from edited topic", () => - notebookTest().then(async ({ id }) => - noteTest().then(async ({ db, id: noteId }) => { - let topics = db.notebooks.notebook(id).topics; - await topics.add("Home"); - let topic = topics.topic("Home"); - await db.notes.addToNotebook({ id, topic: topic._topic.title }, noteId); - await topics.add({ id: topic._topic.id, title: "Hello22" }); - await db.notes.delete(noteId); - }) - )); + notebookTest().then(async ({ db, id }) => { + const noteId = await db.notes.add(TEST_NOTE); + let topics = db.notebooks.notebook(id).topics; + await topics.add("Home"); + let topic = topics.topic("Home"); + await db.notes.addToNotebook({ id, topic: topic._topic.title }, noteId); + await topics.add({ id: topic._topic.id, title: "Hello22" }); + await db.notes.delete(noteId); + })); test("editing one topic should not update dateEdited of all", () => notebookTest().then(async ({ db, id }) => { diff --git a/packages/core/__tests__/trash.test.js b/packages/core/__tests__/trash.test.js index 42711377a..e0acabdb9 100644 --- a/packages/core/__tests__/trash.test.js +++ b/packages/core/__tests__/trash.test.js @@ -19,16 +19,13 @@ along with this program. If not, see . import dayjs from "dayjs"; import { - StorageInterface, noteTest, notebookTest, TEST_NOTE, TEST_NOTEBOOK, databaseTest } from "./utils"; -import { beforeEach, test, expect } from "vitest"; - -beforeEach(() => StorageInterface.clear()); +import { test, expect } from "vitest"; test("trash should be empty", () => databaseTest().then((db) => { diff --git a/packages/core/__tests__/utils/index.js b/packages/core/__tests__/utils/index.js index 5544c61f0..e32e3d530 100644 --- a/packages/core/__tests__/utils/index.js +++ b/packages/core/__tests__/utils/index.js @@ -18,12 +18,14 @@ along with this program. If not, see . */ import DB from "../../src/api"; -import StorageInterface from "../../__mocks__/storage.mock"; +import { NodeStorageInterface } from "../../__mocks__/node-storage.mock"; import dayjs from "dayjs"; import { groupArray } from "../../src/utils/grouping"; import FS from "../../__mocks__/fs.mock"; import Compressor from "../../__mocks__/compressor.mock"; import { expect } from "vitest"; +import EventSource from "eventsource"; +import { randomBytes } from "../../src/utils/random"; const TEST_NOTEBOOK = { title: "Test Notebook", @@ -39,7 +41,7 @@ const TEST_NOTEBOOK2 = { function databaseTest() { let db = new DB(); - db.setup(StorageInterface, null, FS, Compressor); + db.setup(new NodeStorageInterface(), EventSource, FS, Compressor); return db.init().then(() => db); } @@ -94,6 +96,29 @@ function delay(ms) { return new Promise((resolve) => setTimeout(resolve, ms)); } +async function loginFakeUser(db) { + const email = "johndoe@example.com"; + const userSalt = randomBytes(16).toString("base64"); + await db.storage.deriveCryptoKey(`_uk_@${email}`, { + password: "password", + salt: userSalt + }); + + const userEncryptionKey = await db.storage.getCryptoKey(`_uk_@${email}`); + + const key = await db.storage.generateRandomKey(); + const attachmentsKey = await db.storage.encrypt( + { password: userEncryptionKey }, + JSON.stringify(key) + ); + + await db.user.setUser({ + email, + salt: userSalt, + attachmentsKey: attachmentsKey + }); +} + export { databaseTest, notebookTest, @@ -101,10 +126,10 @@ export { groupedTest, IMG_CONTENT, IMG_CONTENT_WITHOUT_HASH, - StorageInterface, TEST_NOTEBOOK, TEST_NOTEBOOK2, TEST_NOTE, LONG_TEXT, - delay + delay, + loginFakeUser }; diff --git a/packages/core/__tests__/vault.test.js b/packages/core/__tests__/vault.test.js index a9767f706..bdb1b2b4a 100644 --- a/packages/core/__tests__/vault.test.js +++ b/packages/core/__tests__/vault.test.js @@ -17,12 +17,8 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { StorageInterface, databaseTest, noteTest, TEST_NOTE } from "./utils"; -import { beforeEach, test, expect } from "vitest"; - -beforeEach(async () => { - StorageInterface.clear(); -}); +import { databaseTest, noteTest, TEST_NOTE } from "./utils"; +import { test, expect } from "vitest"; test("create vault", () => databaseTest().then(async (db) => { @@ -113,11 +109,9 @@ test("save a locked note", () => await db.vault.save(note); const content = await db.content.raw(note.contentId); - const contentData = JSON.parse(content.data.cipher); - expect(contentData.iv).toBeUndefined(); - expect(contentData.cipher).toBeUndefined(); - expect(contentData.key).toBeUndefined(); + expect(content.data.cipher).toBeTypeOf("string"); + expect(() => JSON.parse()).toThrow(); })); test("save an edited locked note", () => @@ -132,11 +126,9 @@ test("save an edited locked note", () => }); const content = await db.content.raw(note.contentId); - const contentData = JSON.parse(content.data.cipher); - expect(contentData.iv).toBeUndefined(); - expect(contentData.cipher).toBeUndefined(); - expect(contentData.key).toBeUndefined(); + expect(content.data.cipher).toBeTypeOf("string"); + expect(() => JSON.parse(content.data.cipher)).toThrow(); })); test("change vault password", () => diff --git a/packages/core/package-lock.json b/packages/core/package-lock.json index aca08d348..cb0227b20 100644 --- a/packages/core/package-lock.json +++ b/packages/core/package-lock.json @@ -32,6 +32,7 @@ "@types/katex": "^0.16.1", "@types/prismjs": "^1.26.0", "@types/showdown": "^2.0.0", + "@vitest/coverage-v8": "^0.34.1", "abortcontroller-polyfill": "^1.7.3", "cross-env": "^7.0.3", "dotenv": "^16.0.1", @@ -61,6 +62,25 @@ "license": "GPL-3.0-or-later", "devDependencies": {} }, + "node_modules/@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, "node_modules/@esbuild/android-arm": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", @@ -413,6 +433,63 @@ "node": ">=12" } }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "node_modules/@microsoft/signalr": { "version": "6.0.11", "resolved": "https://registry.npmjs.org/@microsoft/signalr/-/signalr-6.0.11.tgz", @@ -559,6 +636,12 @@ "integrity": "sha512-FnF3p2FJZ1kJT/0C/lmBzw7HSlH3RhtACVYyrwUsJoCmFNuiLpusWT2FWWB7P9A48CaYpvD6Q2fprn7sZeffpw==", "dev": true }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, "node_modules/@types/katex": { "version": "0.16.1", "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.1.tgz", @@ -589,6 +672,31 @@ "integrity": "sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==", "dev": true }, + "node_modules/@vitest/coverage-v8": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-0.34.1.tgz", + "integrity": "sha512-lRgUwjTMr8idXEbUPSNH4jjRZJXJCVY3BqUa+LDXyJVe3pldxYMn/r0HMqatKUGTp0Kyf1j5LfFoY6kRqRp7jw==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.1", + "@bcoe/v8-coverage": "^0.2.3", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^4.0.1", + "istanbul-reports": "^3.1.5", + "magic-string": "^0.30.1", + "picocolors": "^1.0.0", + "std-env": "^3.3.3", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.1.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": ">=0.32.0 <1" + } + }, "node_modules/@vitest/expect": { "version": "0.34.1", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.1.tgz", @@ -836,11 +944,27 @@ "tslib": "^2.3.1" } }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -917,6 +1041,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, "node_modules/cross-env": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", @@ -1191,6 +1327,12 @@ "node": ">=8" } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -1214,6 +1356,26 @@ "node": "*" } }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/happy-dom": { "version": "10.9.0", "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-10.9.0.tgz", @@ -1228,6 +1390,15 @@ "whatwg-mimetype": "^3.0.0" } }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/hast-util-parse-selector": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", @@ -1258,6 +1429,12 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, "node_modules/html-to-text": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz", @@ -1303,6 +1480,22 @@ "node": ">=0.10.0" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, "node_modules/is-alphabetical": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", @@ -1363,6 +1556,56 @@ "whatwg-fetch": "^3.4.1" } }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", @@ -1450,6 +1693,18 @@ "get-func-name": "^2.0.0" } }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/magic-string": { "version": "0.30.2", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.2.tgz", @@ -1462,11 +1717,20 @@ "node": ">=12" } }, - "node_modules/magic-string/node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/mime-db": { "version": "1.52.0", @@ -1476,6 +1740,18 @@ "node": ">= 0.6" } }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/mlly": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.0.tgz", @@ -1598,6 +1874,15 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, "node_modules/otplib": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/otplib/-/otplib-12.0.1.tgz", @@ -1641,6 +1926,15 @@ "url": "https://ko-fi.com/killymxi" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -1844,6 +2138,21 @@ "url": "https://ko-fi.com/killymxi" } }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -1871,6 +2180,15 @@ "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", @@ -1919,6 +2237,32 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/thirty-two": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz", @@ -2013,6 +2357,20 @@ "requires-port": "^1.0.0" } }, + "node_modules/v8-to-istanbul": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, "node_modules/vite": { "version": "4.4.9", "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz", @@ -2250,6 +2608,12 @@ "node": ">=8" } }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, "node_modules/ws": { "version": "7.5.9", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", @@ -2269,9 +2633,31 @@ "optional": true } } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } }, "dependencies": { + "@ampproject/remapping": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.0", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true + }, "@esbuild/android-arm": { "version": "0.18.20", "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", @@ -2426,6 +2812,51 @@ "dev": true, "optional": true }, + "@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true + }, + "@jridgewell/gen-mapping": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", + "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", + "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, "@microsoft/signalr": { "version": "6.0.11", "resolved": "https://registry.npmjs.org/@microsoft/signalr/-/signalr-6.0.11.tgz", @@ -2559,6 +2990,12 @@ "integrity": "sha512-FnF3p2FJZ1kJT/0C/lmBzw7HSlH3RhtACVYyrwUsJoCmFNuiLpusWT2FWWB7P9A48CaYpvD6Q2fprn7sZeffpw==", "dev": true }, + "@types/istanbul-lib-coverage": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz", + "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==", + "dev": true + }, "@types/katex": { "version": "0.16.1", "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.1.tgz", @@ -2589,6 +3026,25 @@ "integrity": "sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==", "dev": true }, + "@vitest/coverage-v8": { + "version": "0.34.1", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-0.34.1.tgz", + "integrity": "sha512-lRgUwjTMr8idXEbUPSNH4jjRZJXJCVY3BqUa+LDXyJVe3pldxYMn/r0HMqatKUGTp0Kyf1j5LfFoY6kRqRp7jw==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.1", + "@bcoe/v8-coverage": "^0.2.3", + "istanbul-lib-coverage": "^3.2.0", + "istanbul-lib-report": "^3.0.1", + "istanbul-lib-source-maps": "^4.0.1", + "istanbul-reports": "^3.1.5", + "magic-string": "^0.30.1", + "picocolors": "^1.0.0", + "std-env": "^3.3.3", + "test-exclude": "^6.0.0", + "v8-to-istanbul": "^9.1.0" + } + }, "@vitest/expect": { "version": "0.34.1", "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.34.1.tgz", @@ -2773,11 +3229,27 @@ "tslib": "^2.3.1" } }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, "boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -2829,6 +3301,18 @@ "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", "dev": true }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "convert-source-map": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz", + "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==", + "dev": true + }, "cross-env": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", @@ -3021,6 +3505,12 @@ "tough-cookie": "^2.3.3 || ^3.0.1 || ^4.0.0" } }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, "fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -3034,6 +3524,20 @@ "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", "dev": true }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "happy-dom": { "version": "10.9.0", "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-10.9.0.tgz", @@ -3048,6 +3552,12 @@ "whatwg-mimetype": "^3.0.0" } }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, "hast-util-parse-selector": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-3.1.1.tgz", @@ -3070,6 +3580,12 @@ "space-separated-tokens": "^2.0.0" } }, + "html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true + }, "html-to-text": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/html-to-text/-/html-to-text-9.0.5.tgz", @@ -3102,6 +3618,22 @@ "safer-buffer": ">= 2.1.2 < 3.0.0" } }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, "is-alphabetical": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", @@ -3146,6 +3678,44 @@ "whatwg-fetch": "^3.4.1" } }, + "istanbul-lib-coverage": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", + "integrity": "sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw==", + "dev": true + }, + "istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "requires": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + } + }, + "istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "requires": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + } + }, + "istanbul-reports": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.6.tgz", + "integrity": "sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==", + "dev": true, + "requires": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + } + }, "jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", @@ -3215,6 +3785,15 @@ "get-func-name": "^2.0.0" } }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "magic-string": { "version": "0.30.2", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.2.tgz", @@ -3222,14 +3801,15 @@ "dev": true, "requires": { "@jridgewell/sourcemap-codec": "^1.4.15" - }, - "dependencies": { - "@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - } + } + }, + "make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "requires": { + "semver": "^7.5.3" } }, "mime-db": { @@ -3237,6 +3817,15 @@ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==" }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, "mlly": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.0.tgz", @@ -3327,6 +3916,15 @@ "boolbase": "^1.0.0" } }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, "otplib": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/otplib/-/otplib-12.0.1.tgz", @@ -3363,6 +3961,12 @@ "peberminta": "^0.9.0" } }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -3510,6 +4114,15 @@ "parseley": "^0.12.0" } }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -3533,6 +4146,12 @@ "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "source-map-js": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", @@ -3571,6 +4190,26 @@ "acorn": "^8.10.0" } }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "requires": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + } + }, "thirty-two": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz", @@ -3647,6 +4286,17 @@ "requires-port": "^1.0.0" } }, + "v8-to-istanbul": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.1.0.tgz", + "integrity": "sha512-6z3GW9x8G1gd+JIIgQQQxXuiJtCXeAjp6RaPEPLv62mH3iPHPxV6W3robxtCzNErRo6ZwTmzWhsbNvjyEBKzKA==", + "dev": true, + "requires": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^1.6.0" + } + }, "vite": { "version": "4.4.9", "resolved": "https://registry.npmjs.org/vite/-/vite-4.4.9.tgz", @@ -3760,10 +4410,23 @@ "stackback": "0.0.2" } }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, "ws": { "version": "7.5.9", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", - "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==" + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "requires": {} + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true } } } diff --git a/packages/core/package.json b/packages/core/package.json index a43b963a9..e6f2337f0 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -13,6 +13,7 @@ "@types/katex": "^0.16.1", "@types/prismjs": "^1.26.0", "@types/showdown": "^2.0.0", + "@vitest/coverage-v8": "^0.34.1", "abortcontroller-polyfill": "^1.7.3", "cross-env": "^7.0.3", "dotenv": "^16.0.1", diff --git a/packages/core/src/api/sync/__tests__/collector.test.js b/packages/core/src/api/sync/__tests__/collector.test.js index 3ba403577..511744e0e 100644 --- a/packages/core/src/api/sync/__tests__/collector.test.js +++ b/packages/core/src/api/sync/__tests__/collector.test.js @@ -17,18 +17,9 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -import { - databaseTest, - TEST_NOTE, - delay, - StorageInterface -} from "../../../../__tests__/utils"; +import { databaseTest, TEST_NOTE, delay } from "../../../../__tests__/utils"; import Collector from "../collector"; -import { test, beforeEach, expect } from "vitest"; - -beforeEach(async () => { - StorageInterface.clear(); -}); +import { test, expect } from "vitest"; test("newly created note should get included in collector", () => databaseTest().then(async (db) => { diff --git a/packages/core/src/database/backup.js b/packages/core/src/database/backup.js index b2d239156..a17ce3454 100644 --- a/packages/core/src/database/backup.js +++ b/packages/core/src/database/backup.js @@ -49,6 +49,8 @@ export default class Backup { async export(type, encrypt = false) { if (!validTypes.some((t) => t === type)) throw new Error("Invalid type. It must be one of 'mobile' or 'web'."); + if (encrypt && !(await this._db.user.getUser())) + throw new Error("Please login to create encrypted backups."); let keys = await this._db.storage.getAllKeys(); let data = filterData( diff --git a/packages/core/vitest.config.ts b/packages/core/vitest.config.ts index fc4de3443..e968aec1b 100644 --- a/packages/core/vitest.config.ts +++ b/packages/core/vitest.config.ts @@ -25,6 +25,9 @@ export default defineConfig({ test: { environment: "happy-dom", setupFiles: ["./globals.setup.js"], + coverage: { + reporter: ["text", "html"] + }, include: [ ...(IS_E2E ? ["__e2e__/**/*.test.js"] : []), "__tests__/**/*.test.js",