mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-22 14:39:34 +01:00
feat: remove sync tests
these tests are too fragile, hard to maintain and keep up to date. Maybe I will write them again from scratch. As they are, they are of no help.
This commit is contained in:
@@ -1,94 +0,0 @@
|
|||||||
import StorageInterface from "../../../__mocks__/storage.mock";
|
|
||||||
import Collector from "../collector";
|
|
||||||
import { enableFetchMocks, disableFetchMocks } from "jest-fetch-mock";
|
|
||||||
import {
|
|
||||||
noteTest,
|
|
||||||
TEST_NOTE,
|
|
||||||
TEST_NOTEBOOK,
|
|
||||||
databaseTest,
|
|
||||||
} from "../../../__tests__/utils";
|
|
||||||
import { login } from "./utils";
|
|
||||||
|
|
||||||
function getMainCollectionParams(name, testItem) {
|
|
||||||
return [
|
|
||||||
name,
|
|
||||||
(db, collection) => db[collection].add(testItem),
|
|
||||||
(db, collection) =>
|
|
||||||
db[collection].add({
|
|
||||||
...testItem,
|
|
||||||
id: Math.random().toString(),
|
|
||||||
remote: true,
|
|
||||||
dateEdited: 1,
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
function getTagsCollectionParams(name, testItem) {
|
|
||||||
return [
|
|
||||||
name,
|
|
||||||
(db, collection) => db[collection].add(testItem + Math.random(), 2),
|
|
||||||
(db, collection) =>
|
|
||||||
db[collection]._collection.addItem({
|
|
||||||
title: testItem + MAX_ITEMS + 1,
|
|
||||||
noteIds: [2],
|
|
||||||
deletedIds: [],
|
|
||||||
id: Math.random().toString(),
|
|
||||||
remote: true,
|
|
||||||
dateEdited: 1,
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
const MAX_ITEMS = 5;
|
|
||||||
|
|
||||||
const tests = [
|
|
||||||
getMainCollectionParams("notes", TEST_NOTE),
|
|
||||||
getMainCollectionParams("notebooks", TEST_NOTEBOOK),
|
|
||||||
getMainCollectionParams("content", { ops: [{ insert: "true" }] }),
|
|
||||||
];
|
|
||||||
|
|
||||||
describe.each(tests)("%s preparation", (collection, add, addExtra) => {
|
|
||||||
beforeAll(() => {
|
|
||||||
enableFetchMocks();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fetch.resetMocks();
|
|
||||||
StorageInterface.clear();
|
|
||||||
});
|
|
||||||
|
|
||||||
test(`prepare ${collection} when user has never synced before`, () => {
|
|
||||||
return databaseTest().then(async (db) => {
|
|
||||||
await login(db);
|
|
||||||
await Promise.all(
|
|
||||||
Array(MAX_ITEMS)
|
|
||||||
.fill(0)
|
|
||||||
.map(() => add(db, collection))
|
|
||||||
);
|
|
||||||
const collector = new Collector(db);
|
|
||||||
const data = await collector.collect(0);
|
|
||||||
expect(data[collection].length).toBe(MAX_ITEMS);
|
|
||||||
expect(
|
|
||||||
data[collection].every((item) => !!item.iv && !!item.cipher)
|
|
||||||
).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test(`prepare ${collection} when user has synced before`, () => {
|
|
||||||
return databaseTest().then(async (db) => {
|
|
||||||
await login(db);
|
|
||||||
await Promise.all(
|
|
||||||
Array(MAX_ITEMS)
|
|
||||||
.fill(0)
|
|
||||||
.map(() => add(db, collection))
|
|
||||||
);
|
|
||||||
await addExtra(db, collection);
|
|
||||||
const collector = new Collector(db);
|
|
||||||
const data = await collector.collect(10);
|
|
||||||
expect(data[collection].length).toBe(MAX_ITEMS);
|
|
||||||
expect(
|
|
||||||
data[collection].every((item) => !!item.iv && !!item.cipher)
|
|
||||||
).toBeTruthy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
import Merger from "../merger";
|
|
||||||
import {
|
|
||||||
StorageInterface,
|
|
||||||
databaseTest,
|
|
||||||
noteTest,
|
|
||||||
TEST_NOTE,
|
|
||||||
TEST_NOTEBOOK,
|
|
||||||
} from "../../../__tests__/utils";
|
|
||||||
import { enableFetchMocks, disableFetchMocks } from "jest-fetch-mock";
|
|
||||||
import { tagsCollectionParams, mainCollectionParams } from "./utils";
|
|
||||||
import { login, getEncrypted } from "./utils";
|
|
||||||
import { CURRENT_DATABASE_VERSION } from "../../../common";
|
|
||||||
|
|
||||||
const emptyServerResponse = {
|
|
||||||
notes: [],
|
|
||||||
notebooks: [],
|
|
||||||
content: [],
|
|
||||||
settings: [],
|
|
||||||
};
|
|
||||||
|
|
||||||
const testItem = { id: "someId", dateEdited: 2 };
|
|
||||||
|
|
||||||
test("server response with all arrays empty should cause early return", async () => {
|
|
||||||
const merger = new Merger();
|
|
||||||
const result = await merger.merge(emptyServerResponse);
|
|
||||||
expect(result).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("null server response should return false", async () => {
|
|
||||||
const merger = new Merger();
|
|
||||||
const result = await merger.merge();
|
|
||||||
expect(result).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
const tests = [
|
|
||||||
mainCollectionParams("notes", "note", TEST_NOTE),
|
|
||||||
mainCollectionParams("notebooks", "notebook", TEST_NOTEBOOK),
|
|
||||||
];
|
|
||||||
|
|
||||||
describe.each(tests)(
|
|
||||||
"general %s syncing tests",
|
|
||||||
(collection, add, edit, get, itemType) => {
|
|
||||||
beforeAll(() => {
|
|
||||||
enableFetchMocks();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fetch.resetMocks();
|
|
||||||
StorageInterface.clear();
|
|
||||||
});
|
|
||||||
|
|
||||||
test(`merge ${collection} into empty database`, () =>
|
|
||||||
databaseTest().then(async (db) => {
|
|
||||||
await login(db);
|
|
||||||
const merger = new Merger(db);
|
|
||||||
const result = await merger.merge(
|
|
||||||
{
|
|
||||||
[collection]: [
|
|
||||||
{
|
|
||||||
id: testItem.id,
|
|
||||||
v: CURRENT_DATABASE_VERSION,
|
|
||||||
...(await getEncrypted({ ...testItem, type: itemType })),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
synced: false,
|
|
||||||
},
|
|
||||||
0
|
|
||||||
);
|
|
||||||
expect(result).toBe(true);
|
|
||||||
expect(db[collection].all[0].id).toStrictEqual(testItem.id);
|
|
||||||
expect(db[collection].all[0].dateEdited).toStrictEqual(
|
|
||||||
testItem.dateEdited
|
|
||||||
);
|
|
||||||
}));
|
|
||||||
|
|
||||||
test(`merge local and remote ${collection}`, () =>
|
|
||||||
databaseTest().then(async (db) => {
|
|
||||||
await login(db);
|
|
||||||
const merger = new Merger(db);
|
|
||||||
const item = await add(db);
|
|
||||||
item.title = "Google";
|
|
||||||
const result = await merger.merge(
|
|
||||||
{
|
|
||||||
[collection]: [
|
|
||||||
{
|
|
||||||
v: CURRENT_DATABASE_VERSION,
|
|
||||||
id: item.id,
|
|
||||||
...(await getEncrypted(item)),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
synced: false,
|
|
||||||
},
|
|
||||||
0
|
|
||||||
);
|
|
||||||
expect(result).toBe(true);
|
|
||||||
expect(db[collection].all.length).toBe(1);
|
|
||||||
expect(db[collection].all[0]).toStrictEqual(item);
|
|
||||||
}));
|
|
||||||
|
|
||||||
test(`local ${collection} are more updated than remote ones`, () =>
|
|
||||||
databaseTest().then(async (db) => {
|
|
||||||
await login(db);
|
|
||||||
const merger = new Merger(db);
|
|
||||||
const item = await add(db);
|
|
||||||
await edit(db, item);
|
|
||||||
item.title = "Google";
|
|
||||||
const result = await merger.merge(
|
|
||||||
{
|
|
||||||
[collection]: [
|
|
||||||
{
|
|
||||||
id: item.id,
|
|
||||||
v: CURRENT_DATABASE_VERSION,
|
|
||||||
...(await getEncrypted(item)),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
synced: false,
|
|
||||||
},
|
|
||||||
0
|
|
||||||
);
|
|
||||||
expect(result).toBe(true);
|
|
||||||
expect(db[collection].all.length).toBe(1);
|
|
||||||
expect(db[collection].all[0]).toStrictEqual(get(db, item));
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
test("local content updated after lastSyncedTimestamp should cause merge conflict", () => {
|
|
||||||
StorageInterface.clear();
|
|
||||||
return noteTest().then(async ({ db, id }) => {
|
|
||||||
await login(db);
|
|
||||||
|
|
||||||
const contentId = db.notes.note(id).data.contentId;
|
|
||||||
const merger = new Merger(db);
|
|
||||||
const result = await merger.merge(
|
|
||||||
{
|
|
||||||
content: [
|
|
||||||
{
|
|
||||||
id: contentId,
|
|
||||||
v: CURRENT_DATABASE_VERSION,
|
|
||||||
...(await getEncrypted({
|
|
||||||
id: contentId,
|
|
||||||
noteId: id,
|
|
||||||
type: "tiny",
|
|
||||||
data: "<p>my name is</p>",
|
|
||||||
dateEdited: 2919,
|
|
||||||
conflicted: false,
|
|
||||||
resolved: false,
|
|
||||||
})),
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
200
|
|
||||||
);
|
|
||||||
const localContent = await db.content.raw(contentId);
|
|
||||||
expect(localContent.conflicted.id).toBe(contentId);
|
|
||||||
expect(localContent.conflicted.noteId).toBe(id);
|
|
||||||
expect(result).toBe(true);
|
|
||||||
expect(await db.context.read("hasConflicts")).toBe(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
//import User from "../../models/user";
|
|
||||||
import { enableFetchMocks, disableFetchMocks } from "jest-fetch-mock";
|
|
||||||
import { CURRENT_DATABASE_VERSION } from "../../../common";
|
|
||||||
import StorageInterface from "../../../__mocks__/storage.mock";
|
|
||||||
//import Sync from "../sync";
|
|
||||||
//import Collector from "../prepare";
|
|
||||||
import { databaseTest, TEST_NOTE } from "../../../__tests__/utils";
|
|
||||||
import { login, getEncrypted } from "./utils";
|
|
||||||
|
|
||||||
const RESPONSE_PARAMS = {
|
|
||||||
headers: { "Content-Type": "application/json" },
|
|
||||||
};
|
|
||||||
|
|
||||||
beforeAll(() => {
|
|
||||||
enableFetchMocks();
|
|
||||||
});
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
fetch.resetMocks();
|
|
||||||
StorageInterface.clear();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("syncing when user is not logged in should throw", () =>
|
|
||||||
databaseTest().then((db) => {
|
|
||||||
expect(db.sync()).rejects.toThrow("You need to login to sync.");
|
|
||||||
}));
|
|
||||||
|
|
||||||
test("sync without merge conflicts, cause merge conflicts, resolve them and then resync", () => {
|
|
||||||
return databaseTest().then(async (db) => {
|
|
||||||
// 1. login
|
|
||||||
await login(db);
|
|
||||||
|
|
||||||
// 2. create local note
|
|
||||||
const noteId = await db.notes.add(TEST_NOTE);
|
|
||||||
|
|
||||||
// 3. start sync
|
|
||||||
fetchMock
|
|
||||||
.once(JSON.stringify({ notes: [], synced: false }), RESPONSE_PARAMS)
|
|
||||||
.once(
|
|
||||||
JSON.stringify({ lastSynced: Date.now() }),
|
|
||||||
{ status: 200 },
|
|
||||||
RESPONSE_PARAMS
|
|
||||||
);
|
|
||||||
await db.sync();
|
|
||||||
|
|
||||||
/////// CAUSE MERGE CONFLICT! ///////
|
|
||||||
// 4. edit the note's content
|
|
||||||
await db.notes.add({
|
|
||||||
id: noteId,
|
|
||||||
content: { ...TEST_NOTE.content },
|
|
||||||
});
|
|
||||||
|
|
||||||
// 5. sync again and expect conflicts
|
|
||||||
const contentId = db.notes.note(noteId).data.contentId;
|
|
||||||
const content = {
|
|
||||||
id: contentId,
|
|
||||||
v: CURRENT_DATABASE_VERSION,
|
|
||||||
...(await getEncrypted({
|
|
||||||
id: contentId,
|
|
||||||
type: TEST_NOTE.content.type,
|
|
||||||
dateEdited: Date.now(),
|
|
||||||
conflicted: false,
|
|
||||||
data: "<p>hello world what are you doing</p>",
|
|
||||||
})),
|
|
||||||
};
|
|
||||||
|
|
||||||
fetchMock
|
|
||||||
.once(
|
|
||||||
JSON.stringify({ notes: [], content: [content], synced: false }),
|
|
||||||
RESPONSE_PARAMS
|
|
||||||
)
|
|
||||||
.once(
|
|
||||||
JSON.stringify({ lastSynced: Date.now() }),
|
|
||||||
{ status: 200 },
|
|
||||||
RESPONSE_PARAMS
|
|
||||||
);
|
|
||||||
|
|
||||||
await expect(db.sync()).rejects.toThrow(
|
|
||||||
"Merge conflicts detected. Please resolve all conflicts to continue syncing."
|
|
||||||
);
|
|
||||||
|
|
||||||
let rawContent = await db.content.raw(contentId);
|
|
||||||
expect(rawContent.conflicted.id).toBe(contentId);
|
|
||||||
expect(rawContent.conflicted.data).toBeTruthy();
|
|
||||||
|
|
||||||
// 6. Resolve conflicts
|
|
||||||
await db.notes.add({
|
|
||||||
id: noteId,
|
|
||||||
conflicted: false,
|
|
||||||
content: {
|
|
||||||
type: TEST_NOTE.content.type,
|
|
||||||
data: TEST_NOTE.content.data,
|
|
||||||
resolved: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
rawContent = await db.content.raw(contentId);
|
|
||||||
expect(rawContent.conflicted).toBe(false);
|
|
||||||
//expect(rawDelta.resolved).toBe(true);
|
|
||||||
|
|
||||||
// 7. Resync (no conflicts should appear)
|
|
||||||
fetchMock
|
|
||||||
.once(
|
|
||||||
JSON.stringify({ notes: [], content: [content], synced: false }),
|
|
||||||
RESPONSE_PARAMS
|
|
||||||
)
|
|
||||||
.once(
|
|
||||||
JSON.stringify({ lastSynced: Date.now() }),
|
|
||||||
{ status: 200 },
|
|
||||||
RESPONSE_PARAMS
|
|
||||||
);
|
|
||||||
await expect(db.sync()).resolves.toBeUndefined();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
import "jest-fetch-mock";
|
|
||||||
import Storage from "../../../__mocks__/storage.mock";
|
|
||||||
|
|
||||||
const SUCCESS_LOGIN_RESPONSE = {
|
|
||||||
access_token: "access_token",
|
|
||||||
refresh_token: "refresh_token",
|
|
||||||
scope: "sync",
|
|
||||||
expires_in: 3600,
|
|
||||||
};
|
|
||||||
|
|
||||||
const SUCCESS_USER_RESPONSE = {
|
|
||||||
id: "0",
|
|
||||||
email: process.env.EMAIL,
|
|
||||||
salt: "",
|
|
||||||
vaultKey: null,
|
|
||||||
};
|
|
||||||
|
|
||||||
async function login(db) {
|
|
||||||
fetchMock
|
|
||||||
.mockResponseOnce(JSON.stringify(SUCCESS_LOGIN_RESPONSE), {
|
|
||||||
headers: { "Content-Type": "application/json" },
|
|
||||||
})
|
|
||||||
.mockResponseOnce(JSON.stringify(SUCCESS_USER_RESPONSE), {
|
|
||||||
headers: { "Content-Type": "application/json" },
|
|
||||||
});
|
|
||||||
|
|
||||||
await db.user.login(
|
|
||||||
SUCCESS_USER_RESPONSE.email,
|
|
||||||
"password",
|
|
||||||
true,
|
|
||||||
"password"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function mainCollectionParams(collection, itemKey, item) {
|
|
||||||
async function addItem(db) {
|
|
||||||
const id = await db[collection].add(item);
|
|
||||||
return db[collection][itemKey](id).data;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function editItem(db, item) {
|
|
||||||
await db[collection].add({ ...item, title: "dobido" });
|
|
||||||
}
|
|
||||||
|
|
||||||
function getItem(db, item) {
|
|
||||||
return db[collection][itemKey](item.id).data;
|
|
||||||
}
|
|
||||||
|
|
||||||
return [collection, addItem, editItem, getItem, itemKey];
|
|
||||||
}
|
|
||||||
|
|
||||||
function tagsCollectionParams(collection, item, type) {
|
|
||||||
async function addItem(db) {
|
|
||||||
const id = await db[collection].add(item, 20);
|
|
||||||
return db[collection].tag(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function editItem(db) {
|
|
||||||
await db[collection].add(item, 240);
|
|
||||||
}
|
|
||||||
|
|
||||||
function getItem(db, item) {
|
|
||||||
return db[collection].tag(item.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return [collection, addItem, editItem, getItem, type];
|
|
||||||
}
|
|
||||||
|
|
||||||
function getEncrypted(item) {
|
|
||||||
return Storage.encrypt("password", JSON.stringify(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
export { tagsCollectionParams, mainCollectionParams, login, getEncrypted };
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
import { areAllEmpty } from "../utils";
|
|
||||||
|
|
||||||
test("return true if all array items in object are empty", () => {
|
|
||||||
const result = areAllEmpty({ a: [], b: [], c: true, f: 214 });
|
|
||||||
expect(result).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("return false if any array item in object is not empty", () => {
|
|
||||||
const result = areAllEmpty({ a: [2, 3, 4], b: [], c: true, f: 214 });
|
|
||||||
expect(result).toBe(false);
|
|
||||||
});
|
|
||||||
Reference in New Issue
Block a user