mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-21 22:19:41 +01:00
mobile: fix e2e tests
This commit is contained in:
committed by
Abdullah Atta
parent
e36bc816ea
commit
e0a704d022
1
apps/mobile/.gitignore
vendored
1
apps/mobile/.gitignore
vendored
@@ -39,6 +39,7 @@ DerivedData
|
|||||||
*.xcuserstate
|
*.xcuserstate
|
||||||
*.hprof
|
*.hprof
|
||||||
**/.xcode.env.local
|
**/.xcode.env.local
|
||||||
|
native/cache
|
||||||
# Android/IntelliJ
|
# Android/IntelliJ
|
||||||
#
|
#
|
||||||
rn-build-deps/
|
rn-build-deps/
|
||||||
|
|||||||
@@ -311,8 +311,10 @@ export class VaultDialog extends Component {
|
|||||||
loading: true
|
loading: true
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
let verified = await db.user.verifyPassword(this.password);
|
let verified = true;
|
||||||
if (!(await db.user.getUser())) verified = true;
|
if (await db.user.getUser()) {
|
||||||
|
verified = await db.user.verifyPassword(this.password);
|
||||||
|
}
|
||||||
if (verified) {
|
if (verified) {
|
||||||
let noteIds = [];
|
let noteIds = [];
|
||||||
if (this.state.deleteAll) {
|
if (this.state.deleteAll) {
|
||||||
@@ -320,20 +322,21 @@ export class VaultDialog extends Component {
|
|||||||
const relations = await db.relations.from(vault, "note").get();
|
const relations = await db.relations.from(vault, "note").get();
|
||||||
noteIds = relations.map((item) => item.toId);
|
noteIds = relations.map((item) => item.toId);
|
||||||
}
|
}
|
||||||
|
|
||||||
await db.vault.delete(this.state.deleteAll);
|
await db.vault.delete(this.state.deleteAll);
|
||||||
|
|
||||||
noteIds.forEach((id) => {
|
if (this.state.deleteAll) {
|
||||||
eSendEvent(
|
noteIds.forEach((id) => {
|
||||||
eUpdateNoteInEditor,
|
eSendEvent(
|
||||||
{
|
eUpdateNoteInEditor,
|
||||||
id: id,
|
{
|
||||||
deleted: true
|
id: id,
|
||||||
},
|
deleted: true
|
||||||
true
|
},
|
||||||
);
|
true
|
||||||
});
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
console.log("VAULT UPDATED EVENT");
|
||||||
eSendEvent("vaultUpdated");
|
eSendEvent("vaultUpdated");
|
||||||
this.setState({
|
this.setState({
|
||||||
loading: false
|
loading: false
|
||||||
@@ -517,7 +520,6 @@ export class VaultDialog extends Component {
|
|||||||
});
|
});
|
||||||
this.close();
|
this.close();
|
||||||
} else {
|
} else {
|
||||||
eSendEvent("vaultUpdated");
|
|
||||||
ToastManager.show({
|
ToastManager.show({
|
||||||
heading: strings.vaultCreated(),
|
heading: strings.vaultCreated(),
|
||||||
type: "success",
|
type: "success",
|
||||||
@@ -525,6 +527,7 @@ export class VaultDialog extends Component {
|
|||||||
});
|
});
|
||||||
this.close();
|
this.close();
|
||||||
}
|
}
|
||||||
|
eSendEvent("vaultUpdated");
|
||||||
}
|
}
|
||||||
|
|
||||||
_permanantUnlock() {
|
_permanantUnlock() {
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ export const NotebookSheet = () => {
|
|||||||
backgroundInteractionEnabled
|
backgroundInteractionEnabled
|
||||||
gestureEnabled
|
gestureEnabled
|
||||||
>
|
>
|
||||||
<View
|
{/* <View
|
||||||
style={{
|
style={{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
right: 24 + normalize(50),
|
right: 24 + normalize(50),
|
||||||
@@ -214,17 +214,11 @@ export const NotebookSheet = () => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Pressable
|
<Pressable
|
||||||
testID={notesnook.buttons.add}
|
testID="add-notebook-button"
|
||||||
type="secondary"
|
type="secondary"
|
||||||
onPress={() => {
|
onPress={() => {
|
||||||
if (!notebook) return;
|
if (!notebook) return;
|
||||||
AddNotebookSheet.present(
|
|
||||||
undefined,
|
|
||||||
notebook,
|
|
||||||
undefined,
|
|
||||||
undefined,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
borderRadius: 100
|
borderRadius: 100
|
||||||
@@ -245,7 +239,7 @@ export const NotebookSheet = () => {
|
|||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
</Pressable>
|
</Pressable>
|
||||||
</View>
|
</View> */}
|
||||||
|
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
@@ -404,6 +398,27 @@ export const NotebookSheet = () => {
|
|||||||
height: 40 * fontScale
|
height: 40 * fontScale
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<IconButton
|
||||||
|
testID="add-notebook-button"
|
||||||
|
name="notebook-plus"
|
||||||
|
onPress={() => {
|
||||||
|
if (!notebook) return;
|
||||||
|
AddNotebookSheet.present(
|
||||||
|
undefined,
|
||||||
|
notebook,
|
||||||
|
undefined,
|
||||||
|
undefined,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
color={colors.primary.icon}
|
||||||
|
size={22}
|
||||||
|
style={{
|
||||||
|
width: 40 * fontScale,
|
||||||
|
height: 40 * fontScale
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
@@ -958,7 +958,9 @@ export const useActions = ({
|
|||||||
title:
|
title:
|
||||||
item.type !== "notebook" && item.type !== "note"
|
item.type !== "notebook" && item.type !== "note"
|
||||||
? strings.doActions.delete[
|
? strings.doActions.delete[
|
||||||
item.type as keyof typeof strings.doActions.delete
|
item.type === "trash"
|
||||||
|
? item.itemType
|
||||||
|
: (item.type as keyof typeof strings.doActions.delete)
|
||||||
](1)
|
](1)
|
||||||
: strings.moveToTrash(),
|
: strings.moveToTrash(),
|
||||||
icon: "delete-outline",
|
icon: "delete-outline",
|
||||||
|
|||||||
@@ -18,11 +18,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { useCallback, useEffect } from "react";
|
import React, { useCallback, useEffect } from "react";
|
||||||
|
import { db } from "../common/database";
|
||||||
import BiometricService from "../services/biometrics";
|
import BiometricService from "../services/biometrics";
|
||||||
import { eSubscribeEvent, eUnSubscribeEvent } from "../services/event-manager";
|
import { eSubscribeEvent, eUnSubscribeEvent } from "../services/event-manager";
|
||||||
import { db } from "../common/database";
|
|
||||||
|
|
||||||
const VaultStatusCache = {
|
const VaultStatusDefaults = {
|
||||||
exists: false,
|
exists: false,
|
||||||
biometryEnrolled: false,
|
biometryEnrolled: false,
|
||||||
isBiometryAvailable: false
|
isBiometryAvailable: false
|
||||||
@@ -35,18 +35,12 @@ export type VaultStatusType = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const useVaultStatus = () => {
|
export const useVaultStatus = () => {
|
||||||
const [vaultStatus, setVaultStatus] = React.useState(VaultStatusCache);
|
const [vaultStatus, setVaultStatus] = React.useState(VaultStatusDefaults);
|
||||||
|
|
||||||
const checkVaultStatus = useCallback(() => {
|
const checkVaultStatus = useCallback(() => {
|
||||||
db.vault?.exists().then(async (exists) => {
|
db.vault?.exists().then(async (exists) => {
|
||||||
const available = await BiometricService.isBiometryAvailable();
|
const available = await BiometricService.isBiometryAvailable();
|
||||||
const fingerprint = await BiometricService.hasInternetCredentials();
|
const fingerprint = await BiometricService.hasInternetCredentials();
|
||||||
if (
|
|
||||||
VaultStatusCache.exists === exists &&
|
|
||||||
VaultStatusCache.biometryEnrolled === fingerprint &&
|
|
||||||
VaultStatusCache.isBiometryAvailable === available
|
|
||||||
)
|
|
||||||
return;
|
|
||||||
setVaultStatus({
|
setVaultStatus({
|
||||||
exists: exists,
|
exists: exists,
|
||||||
biometryEnrolled: fingerprint,
|
biometryEnrolled: fingerprint,
|
||||||
|
|||||||
29
apps/mobile/e2e/globalSetup.ts
Normal file
29
apps/mobile/e2e/globalSetup.ts
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { execSync } from "child_process";
|
||||||
|
|
||||||
|
import { pathExists, ensureDir } from "fs-extra";
|
||||||
|
|
||||||
|
import { resolveConfig } from "detox/internals";
|
||||||
|
import { globalSetup } from "detox/runners/jest";
|
||||||
|
|
||||||
|
export default async function customGlobalSetup() {
|
||||||
|
const config = await resolveConfig();
|
||||||
|
if (config.device.type === "android.emulator") {
|
||||||
|
await downloadTestButlerAPK();
|
||||||
|
}
|
||||||
|
|
||||||
|
await globalSetup();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function downloadTestButlerAPK() {
|
||||||
|
const version = "2.2.1";
|
||||||
|
const artifactUrl = `https://repo1.maven.org/maven2/com/linkedin/testbutler/test-butler-app/${version}/test-butler-app-${version}.apk`;
|
||||||
|
const filePath = `cache/test-butler-app.apk`;
|
||||||
|
|
||||||
|
await ensureDir("cache");
|
||||||
|
if (!(await pathExists(filePath))) {
|
||||||
|
console.log(`\nDownloading Test-Butler APK v${version}...`);
|
||||||
|
execSync(`curl -f -o ${filePath} ${artifactUrl}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = customGlobalSetup;
|
||||||
@@ -1,20 +1,21 @@
|
|||||||
/** @type {import('@jest/types').Config.InitialOptions} */
|
/** @type {import('@jest/types').Config.InitialOptions} */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
rootDir: "..",
|
rootDir: "..",
|
||||||
testMatch: ["<rootDir>/e2e/**/*.e2e.js"],
|
|
||||||
testTimeout: 120000,
|
|
||||||
maxWorkers: 1,
|
maxWorkers: 1,
|
||||||
setupFilesAfterEnv: ["./e2e/setup.js"],
|
testTimeout: 120000,
|
||||||
globalSetup: "detox/runners/jest/globalSetup",
|
globalSetup: "./e2e/globalSetup.ts",
|
||||||
globalTeardown: "detox/runners/jest/globalTeardown",
|
globalTeardown: "detox/runners/jest/globalTeardown",
|
||||||
reporters: ["detox/runners/jest/reporter"],
|
setupFilesAfterEnv: ["./e2e/setup.ts"],
|
||||||
testEnvironment: "detox/runners/jest/testEnvironment",
|
testEnvironment: "detox/runners/jest/testEnvironment",
|
||||||
verbose: true,
|
reporters: ["detox/runners/jest/reporter"],
|
||||||
|
testRunner: "jest-circus/runner",
|
||||||
|
testMatch: ["<rootDir>/e2e/**/*.e2e.(js|ts)"],
|
||||||
transform: {
|
transform: {
|
||||||
"^.+\\.(js|jsx|ts|tsx)$": [
|
"\\.tsx?$": "ts-jest",
|
||||||
|
"^.+\\.(js|jsx)$": [
|
||||||
"babel-jest",
|
"babel-jest",
|
||||||
{ configFile: "../native/babel.config.js" }
|
{ configFile: "../native/babel.config.js" }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
transformIgnorePatterns: ["<rootDir>/../node_modules/"]
|
verbose: true
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ async function login() {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
describe("AUTH", () => {
|
describe("AUTH", () => {
|
||||||
it("Login", async () => {
|
it.skip("Login", async () => {
|
||||||
await prepare();
|
await prepare();
|
||||||
await openSideMenu();
|
await openSideMenu();
|
||||||
await login();
|
await login();
|
||||||
|
|||||||
@@ -17,23 +17,22 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { navigate, tapByText, prepare, sleep } from "./utils";
|
import { Tests } from "./utils";
|
||||||
|
|
||||||
describe("APP LAUNCH AND NAVIGATION", () => {
|
describe("APP LAUNCH AND NAVIGATION", () => {
|
||||||
it("App should launch successfully & hide welcome screen", async () => {
|
it("App should launch successfully & hide welcome screen", async () => {
|
||||||
await prepare();
|
await Tests.prepare();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Basic navigation should work", async () => {
|
it("Basic navigation should work", async () => {
|
||||||
await prepare();
|
await Tests.prepare();
|
||||||
await navigate("Notebooks");
|
await Tests.navigate("Notebooks");
|
||||||
await sleep(500);
|
await Tests.navigate("Favorites");
|
||||||
await navigate("Favorites");
|
await Tests.navigate("Trash");
|
||||||
await navigate("Trash");
|
await Tests.navigate("Tags");
|
||||||
await navigate("Tags");
|
await Tests.navigate("Settings");
|
||||||
await navigate("Settings");
|
await Tests.navigate("Monographs");
|
||||||
await navigate("Monographs");
|
await Tests.navigate("Reminders");
|
||||||
await navigate("Reminders");
|
await Tests.navigate("Notes");
|
||||||
await navigate("Notes");
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1,140 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { notesnook } from "../test.ids";
|
|
||||||
import {
|
|
||||||
navigate,
|
|
||||||
tapById,
|
|
||||||
visibleByText,
|
|
||||||
createNote,
|
|
||||||
prepare,
|
|
||||||
visibleById,
|
|
||||||
notVisibleById,
|
|
||||||
sleep,
|
|
||||||
exitEditor,
|
|
||||||
tapByText,
|
|
||||||
elementByText,
|
|
||||||
elementById
|
|
||||||
} from "./utils";
|
|
||||||
|
|
||||||
describe("NOTE TESTS", () => {
|
|
||||||
it("Create a note in editor", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Open and close a note", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote();
|
|
||||||
await tapById(notesnook.ids.note.get(0));
|
|
||||||
await exitEditor();
|
|
||||||
});
|
|
||||||
|
|
||||||
it.only("Notes properties should show", async () => {
|
|
||||||
await prepare();
|
|
||||||
let note = await createNote();
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
await waitFor(elementByText("Created at:")).toBeVisible().withTimeout(500);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Favorite and unfavorite a note", async () => {
|
|
||||||
await prepare();
|
|
||||||
let note = await createNote();
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
await tapById("icon-favorite");
|
|
||||||
await visibleById("icon-star");
|
|
||||||
await navigate("Favorites");
|
|
||||||
await visibleByText(note.body);
|
|
||||||
await sleep(500);
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
await tapById("icon-favorite");
|
|
||||||
await expect(element(by.text(note.body))).not.toBeVisible();
|
|
||||||
await navigate("Notes");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Pin a note to top", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote();
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
await tapById("icon-pin");
|
|
||||||
await visibleByText("Pinned");
|
|
||||||
await visibleById("icon-pinned");
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
await tapById("icon-pin");
|
|
||||||
expect(element(by.id("icon-pinned"))).not.toBeVisible();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Pin a note in notifications", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote();
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
await tapById("icon-pin-to-notifications");
|
|
||||||
await visibleByText("Unpin from notifications");
|
|
||||||
await sleep(500);
|
|
||||||
await tapById("icon-pin-to-notifications");
|
|
||||||
await sleep(500);
|
|
||||||
await visibleByText("Pin to notifications");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Copy note", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote();
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
await sleep(1000);
|
|
||||||
await waitFor(elementById("icon-copy")).toBeVisible().withTimeout(500);
|
|
||||||
await tapById("icon-copy");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Assign colors to a note", async () => {
|
|
||||||
await prepare();
|
|
||||||
let note = await createNote();
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
await sleep(1000);
|
|
||||||
await tapByText("Add color");
|
|
||||||
await sleep(500);
|
|
||||||
await elementById("color-title-input").typeText("Test color");
|
|
||||||
await tapByText("Add color");
|
|
||||||
await sleep(3000);
|
|
||||||
await visibleById("icon-check");
|
|
||||||
await tapById("icon-color-#efefef");
|
|
||||||
await notVisibleById("icon-check");
|
|
||||||
await tapById("icon-color-#efefef");
|
|
||||||
await device.pressBack();
|
|
||||||
await navigate("Test color");
|
|
||||||
await visibleByText(note.body);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Delete & restore a note", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote();
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
await sleep(500);
|
|
||||||
await tapById("icon-trash");
|
|
||||||
await navigate("Trash");
|
|
||||||
await sleep(500);
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Restore note");
|
|
||||||
await device.pressBack();
|
|
||||||
await sleep(500);
|
|
||||||
await visibleByText(
|
|
||||||
"Test note description that is very long and should not fit in text."
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
116
apps/mobile/e2e/tests/note.e2e.ts
Normal file
116
apps/mobile/e2e/tests/note.e2e.ts
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { notesnook } from "../test.ids";
|
||||||
|
import { Tests } from "./utils";
|
||||||
|
|
||||||
|
describe("NOTE TESTS", () => {
|
||||||
|
it("Create a note in editor", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Open and close a note", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote();
|
||||||
|
await Tests.fromId(notesnook.ids.note.get(0)).waitAndTap();
|
||||||
|
await Tests.exitEditor();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Notes properties should show", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote();
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await Tests.fromText("Created at").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Favorite and unfavorite a note", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
let note = await Tests.createNote();
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await Tests.fromId("icon-favorite").waitAndTap();
|
||||||
|
await Tests.fromId("icon-star").isVisible();
|
||||||
|
await Tests.navigate("Favorites");
|
||||||
|
await Tests.fromText(note.body).isVisible();
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await Tests.fromId("icon-favorite").waitAndTap();
|
||||||
|
await Tests.fromText(note.body).isNotVisible();
|
||||||
|
await Tests.navigate("Notes");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Pin a note to top", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote();
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await Tests.fromId("icon-pin").waitAndTap();
|
||||||
|
await Tests.fromText("Pinned").isVisible();
|
||||||
|
await Tests.fromId("icon-pinned").isVisible();
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await Tests.fromId("icon-pin").waitAndTap();
|
||||||
|
await Tests.fromText("icon-pinned").isNotVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Pin a note in notifications", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote();
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await Tests.fromId("icon-pin-to-notifications").waitAndTap();
|
||||||
|
await Tests.fromText("Unpin from notifications").isVisible();
|
||||||
|
await Tests.fromId("icon-pin-to-notifications").waitAndTap();
|
||||||
|
await Tests.fromText("Pin to notifications").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Copy note", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote();
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await Tests.fromId("icon-copy").isVisible();
|
||||||
|
await Tests.fromId("icon-copy").waitAndTap();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Assign colors to a note", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
let note = await Tests.createNote();
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await Tests.fromText("Add color").waitAndTap();
|
||||||
|
await Tests.fromId("color-title-input").element.typeText("Test color");
|
||||||
|
await Tests.fromText("Add color").waitAndTap();
|
||||||
|
await Tests.fromId("icon-check").isVisible();
|
||||||
|
await Tests.fromId("icon-color-#efefef").waitAndTap();
|
||||||
|
await Tests.fromId("icon-check").isNotVisible();
|
||||||
|
await Tests.fromId("icon-color-#efefef").waitAndTap();
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.navigate("Test color");
|
||||||
|
await Tests.fromText(note.body).isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it.only("Delete & restore a note", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote();
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await Tests.fromId("icon-trash").waitAndTap();
|
||||||
|
await Tests.navigate("Trash");
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await Tests.fromText("Restore note").waitAndTap();
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.fromText(
|
||||||
|
"Test note description that is very long and should not fit in text."
|
||||||
|
).isVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,309 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { notesnook } from "../test.ids";
|
|
||||||
import {
|
|
||||||
tapById,
|
|
||||||
elementById,
|
|
||||||
visibleByText,
|
|
||||||
tapByText,
|
|
||||||
createNote,
|
|
||||||
prepare,
|
|
||||||
notVisibleById,
|
|
||||||
navigate,
|
|
||||||
elementByText,
|
|
||||||
sleep,
|
|
||||||
notVisibleByText,
|
|
||||||
visibleById,
|
|
||||||
createNotebook
|
|
||||||
} from "./utils";
|
|
||||||
|
|
||||||
// async function addTopic(title = "Topic") {
|
|
||||||
// await tapById(notesnook.buttons.add);
|
|
||||||
// await elementById("input-title").typeText(title);
|
|
||||||
// await tapByText("Add");
|
|
||||||
// await sleep(500);
|
|
||||||
// }
|
|
||||||
|
|
||||||
describe("NOTEBOOKS", () => {
|
|
||||||
it("Create a notebook with title only", async () => {
|
|
||||||
await prepare();
|
|
||||||
await navigate("Notebooks");
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Add your first notebook");
|
|
||||||
await createNotebook("Notebook 1", false, false);
|
|
||||||
await sleep(500);
|
|
||||||
await device.pressBack();
|
|
||||||
await sleep(500);
|
|
||||||
await visibleByText("Notebook 1");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Create a notebook title & description", async () => {
|
|
||||||
await prepare();
|
|
||||||
await navigate("Notebooks");
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Add your first notebook");
|
|
||||||
await createNotebook("Notebook 1", true, false);
|
|
||||||
await sleep(500);
|
|
||||||
await device.pressBack();
|
|
||||||
await sleep(500);
|
|
||||||
await visibleByText("Notebook 1");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Create a notebook, move notes", async () => {
|
|
||||||
await prepare();
|
|
||||||
let note = await createNote();
|
|
||||||
await navigate("Notebooks");
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Add your first notebook");
|
|
||||||
await createNotebook("Notebook 1", true, true);
|
|
||||||
await sleep(500);
|
|
||||||
await tapById("listitem.select");
|
|
||||||
await tapByText("Move selected notes");
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Notebook 1");
|
|
||||||
await sleep(500);
|
|
||||||
await visibleByText(note.body);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Add a sub notebook to a notebook", async () => {
|
|
||||||
await prepare();
|
|
||||||
await navigate("Notebooks");
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Add your first notebook");
|
|
||||||
await createNotebook("Notebook 1", true, false);
|
|
||||||
await sleep(500);
|
|
||||||
await device.pressBack();
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Notebook 1");
|
|
||||||
await sleep(500);
|
|
||||||
await tapById("add-notebook-button");
|
|
||||||
await createNotebook("Sub notebook", true, true);
|
|
||||||
await sleep(500);
|
|
||||||
await device.pressBack();
|
|
||||||
await visibleByText("Sub notebook");
|
|
||||||
await tapById(notesnook.ids.notebook.menu);
|
|
||||||
await tapByText("Move to trash");
|
|
||||||
await sleep(300);
|
|
||||||
await tapByText("Delete");
|
|
||||||
await notVisibleByText("Sub notebook");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Remove a sub notebook from notebook", async () => {
|
|
||||||
await prepare();
|
|
||||||
await navigate("Notebooks");
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Add your first notebook");
|
|
||||||
await createNotebook("Notebook 1", true, false);
|
|
||||||
await sleep(500);
|
|
||||||
await device.pressBack();
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Notebook 1");
|
|
||||||
await sleep(500);
|
|
||||||
await tapById("add-notebook-button");
|
|
||||||
await createNotebook("Sub notebook", true, true);
|
|
||||||
await sleep(500);
|
|
||||||
await device.pressBack();
|
|
||||||
await visibleByText("Sub notebook");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Edit notebook", async () => {
|
|
||||||
await prepare();
|
|
||||||
await navigate("Notebooks");
|
|
||||||
await sleep(500);
|
|
||||||
await tapById(notesnook.buttons.add);
|
|
||||||
await createNotebook("Notebook 1", true);
|
|
||||||
await sleep(500);
|
|
||||||
await device.pressBack();
|
|
||||||
await tapById(notesnook.ids.notebook.menu);
|
|
||||||
await tapByText("Edit notebook");
|
|
||||||
await elementById(notesnook.ids.dialogs.notebook.inputs.title).typeText(
|
|
||||||
" (edited)"
|
|
||||||
);
|
|
||||||
await tapByText("Save");
|
|
||||||
await visibleByText("Notebook 1 (edited)");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Edit a sub notebook", async () => {
|
|
||||||
await prepare();
|
|
||||||
await navigate("Notebooks");
|
|
||||||
await sleep(500);
|
|
||||||
await tapById(notesnook.buttons.add);
|
|
||||||
await createNotebook("Notebook 1", true);
|
|
||||||
await sleep(500);
|
|
||||||
await device.pressBack();
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Notebook 1");
|
|
||||||
await sleep(500);
|
|
||||||
await tapById("add-notebook-button");
|
|
||||||
await createNotebook("Sub notebook", true, true);
|
|
||||||
await device.pressBack();
|
|
||||||
await sleep(500);
|
|
||||||
await tapById(notesnook.ids.notebook.menu);
|
|
||||||
await tapByText("Edit notebook");
|
|
||||||
await sleep(500);
|
|
||||||
await elementById(notesnook.ids.dialogs.notebook.inputs.title).typeText(
|
|
||||||
" (edited)"
|
|
||||||
);
|
|
||||||
await tapByText("Save");
|
|
||||||
await sleep(500);
|
|
||||||
await visibleByText("Sub notebook (edited)");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Add a note to notebook", async () => {
|
|
||||||
await prepare();
|
|
||||||
await navigate("Notebooks");
|
|
||||||
await tapByText("Add your first notebook");
|
|
||||||
await sleep(500);
|
|
||||||
await createNotebook("Notebook 1", true, true);
|
|
||||||
await sleep(500);
|
|
||||||
await device.pressBack();
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Notebook 1");
|
|
||||||
await createNote();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Remove note from Notebook", async () => {
|
|
||||||
await prepare();
|
|
||||||
await navigate("Notebooks");
|
|
||||||
await tapByText("Add your first notebook");
|
|
||||||
await createNotebook("Notebook 1", true, true);
|
|
||||||
await sleep(500);
|
|
||||||
await device.pressBack();
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Notebook 1");
|
|
||||||
await sleep(500);
|
|
||||||
let note = await createNote();
|
|
||||||
await elementByText(note.body).longPress();
|
|
||||||
await tapById("select-minus");
|
|
||||||
await notVisibleById(note.title);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Add/Remove note to notebook from home", async () => {
|
|
||||||
await prepare();
|
|
||||||
await navigate("Notebooks");
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Add your first notebook");
|
|
||||||
await createNotebook("Notebook 1", true, false);
|
|
||||||
await sleep(500);
|
|
||||||
await device.pressBack();
|
|
||||||
await sleep(500);
|
|
||||||
await navigate("Notes");
|
|
||||||
await createNote();
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
await tapById("icon-notebooks");
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Notebook 1");
|
|
||||||
await tapByText("Save");
|
|
||||||
await sleep(300);
|
|
||||||
await visibleByText("Notebook 1");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Edit notebook title, description", async () => {
|
|
||||||
await prepare();
|
|
||||||
await navigate("Notebooks");
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Add your first notebook");
|
|
||||||
await createNotebook();
|
|
||||||
await sleep(500);
|
|
||||||
await device.pressBack();
|
|
||||||
await sleep(500);
|
|
||||||
await visibleByText("Notebook 1");
|
|
||||||
await tapById(notesnook.ids.notebook.menu);
|
|
||||||
await tapByText("Edit notebook");
|
|
||||||
await sleep(500);
|
|
||||||
await elementById(notesnook.ids.dialogs.notebook.inputs.title).typeText(
|
|
||||||
" (Edited)"
|
|
||||||
);
|
|
||||||
await elementById(
|
|
||||||
notesnook.ids.dialogs.notebook.inputs.description
|
|
||||||
).clearText();
|
|
||||||
await elementById(
|
|
||||||
notesnook.ids.dialogs.notebook.inputs.description
|
|
||||||
).typeText("Description of Notebook 1 (Edited)");
|
|
||||||
|
|
||||||
await tapByText("Save");
|
|
||||||
await sleep(500);
|
|
||||||
await visibleByText("Notebook 1 (Edited)");
|
|
||||||
await visibleByText("Description of Notebook 1 (Edited)");
|
|
||||||
});
|
|
||||||
|
|
||||||
it.skip("Move notebook to trash", async () => {
|
|
||||||
await prepare();
|
|
||||||
await navigate("Notebooks");
|
|
||||||
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Add your first notebook");
|
|
||||||
await createNotebook("Notebook 1", false, false);
|
|
||||||
await sleep(500);
|
|
||||||
await device.pressBack();
|
|
||||||
await sleep(500);
|
|
||||||
await visibleByText("Notebook 1");
|
|
||||||
await tapById(notesnook.ids.notebook.menu);
|
|
||||||
await tapByText("Move to trash");
|
|
||||||
await sleep(2000);
|
|
||||||
await tapByText("Delete");
|
|
||||||
await sleep(4000);
|
|
||||||
await navigate("Trash");
|
|
||||||
await visibleByText("Notebook 1");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Move notebook to trash with notes", async () => {
|
|
||||||
await prepare();
|
|
||||||
let note = await createNote();
|
|
||||||
await navigate("Notebooks");
|
|
||||||
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Add your first notebook");
|
|
||||||
await createNotebook("Notebook 1", false, true);
|
|
||||||
await sleep(500);
|
|
||||||
await tapById("listitem.select");
|
|
||||||
await tapByText("Move selected notes");
|
|
||||||
await sleep(500);
|
|
||||||
await visibleByText("Notebook 1");
|
|
||||||
await tapById(notesnook.ids.notebook.menu);
|
|
||||||
await tapByText("Move to trash");
|
|
||||||
await sleep(2000);
|
|
||||||
await tapByText("Move all notes in this notebook to trash");
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Delete");
|
|
||||||
await sleep(4000);
|
|
||||||
await navigate("Trash");
|
|
||||||
await visibleByText("Notebook 1");
|
|
||||||
await visibleByText(note.body);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Pin notebook to side menu", async () => {
|
|
||||||
await prepare();
|
|
||||||
await navigate("Notebooks");
|
|
||||||
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Add your first notebook");
|
|
||||||
await createNotebook("Notebook 1", false, false);
|
|
||||||
await sleep(500);
|
|
||||||
await device.pressBack();
|
|
||||||
await sleep(500);
|
|
||||||
await visibleByText("Notebook 1");
|
|
||||||
await tapById(notesnook.ids.notebook.menu);
|
|
||||||
await tapByText("Add Shortcut");
|
|
||||||
let menu = elementById(notesnook.ids.default.header.buttons.left);
|
|
||||||
await menu.tap();
|
|
||||||
await visibleByText("Notebook 1");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
233
apps/mobile/e2e/tests/notebook.e2e.ts
Normal file
233
apps/mobile/e2e/tests/notebook.e2e.ts
Normal file
@@ -0,0 +1,233 @@
|
|||||||
|
/*
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { notesnook } from "../test.ids";
|
||||||
|
import { Tests } from "./utils";
|
||||||
|
|
||||||
|
describe("NOTEBOOKS", () => {
|
||||||
|
it("Create a notebook with title only", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.navigate("Notebooks");
|
||||||
|
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||||
|
await Tests.createNotebook("Notebook 1", false);
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.fromText("Notebook 1").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Create a notebook title & description", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.navigate("Notebooks");
|
||||||
|
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||||
|
await Tests.createNotebook("Notebook 1", true);
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.fromText("Notebook 1").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Create a notebook, move notes", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
let note = await Tests.createNote();
|
||||||
|
await Tests.navigate("Notebooks");
|
||||||
|
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||||
|
await Tests.createNotebook("Notebook 1", true);
|
||||||
|
await Tests.fromId("listitem.select").waitAndTap();
|
||||||
|
await Tests.fromText("Move selected notes").waitAndTap();
|
||||||
|
await Tests.fromText("Notebook 1").waitAndTap();
|
||||||
|
await Tests.fromText(note.body).isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Add a sub notebook to a notebook", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.navigate("Notebooks");
|
||||||
|
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||||
|
await Tests.createNotebook("Notebook 1", true);
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.fromText("Notebook 1").waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromId("add-notebook-button").waitAndTap();
|
||||||
|
await Tests.createNotebook("Sub notebook", true);
|
||||||
|
await Tests.fromText("Sub notebook").isVisible();
|
||||||
|
await Tests.fromId(notesnook.ids.notebook.menu).waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromText("Move to trash").waitAndTap();
|
||||||
|
await Tests.fromText("Delete").waitAndTap();
|
||||||
|
await Tests.fromText("Sub notebook").isNotVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Remove a sub notebook from notebook", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.navigate("Notebooks");
|
||||||
|
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||||
|
await Tests.createNotebook("Notebook 1", true);
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.fromText("Notebook 1").waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromId("add-notebook-button").waitAndTap();
|
||||||
|
await Tests.createNotebook("Sub notebook", true);
|
||||||
|
await Tests.fromText("Sub notebook").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Edit notebook", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.navigate("Notebooks");
|
||||||
|
await Tests.fromId(notesnook.buttons.add).waitAndTap();
|
||||||
|
await Tests.createNotebook("Notebook 1", true);
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.fromId(notesnook.ids.notebook.menu).waitAndTap();
|
||||||
|
await Tests.fromText("Edit notebook").waitAndTap();
|
||||||
|
await Tests.fromId(
|
||||||
|
notesnook.ids.dialogs.notebook.inputs.title
|
||||||
|
).element.typeText(" (edited)");
|
||||||
|
await Tests.fromText("Save").waitAndTap();
|
||||||
|
await Tests.fromText("Notebook 1 (edited)").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Edit a sub notebook", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.navigate("Notebooks");
|
||||||
|
await Tests.fromId(notesnook.buttons.add).waitAndTap();
|
||||||
|
await Tests.createNotebook("Notebook 1", true);
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.fromText("Notebook 1").waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromId("add-notebook-button").waitAndTap();
|
||||||
|
await Tests.createNotebook("Sub notebook", true);
|
||||||
|
await Tests.fromId(notesnook.ids.notebook.menu).waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromText("Edit notebook").waitAndTap();
|
||||||
|
await Tests.fromId(
|
||||||
|
notesnook.ids.dialogs.notebook.inputs.title
|
||||||
|
).element.typeText(" (edited)");
|
||||||
|
await Tests.fromText("Save").waitAndTap();
|
||||||
|
await Tests.fromText("Sub notebook (edited)").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Add a note to notebook", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.navigate("Notebooks");
|
||||||
|
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||||
|
await Tests.createNotebook("Notebook 1", true);
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.fromText("Notebook 1").waitAndTap();
|
||||||
|
await Tests.createNote();
|
||||||
|
});
|
||||||
|
|
||||||
|
it.skip("Remove note from Notebook", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.navigate("Notebooks");
|
||||||
|
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||||
|
await Tests.createNotebook("Notebook 1", true);
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.fromText("Notebook 1").waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
let note = await Tests.createNote();
|
||||||
|
await Tests.fromText(note.body).element.longPress();
|
||||||
|
await Tests.fromId("select-minus").waitAndTap();
|
||||||
|
await Tests.fromId(note.title).isNotVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Add/Remove note to notebook from home", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.navigate("Notebooks");
|
||||||
|
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||||
|
await Tests.createNotebook("Notebook 1", true);
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.navigate("Notes");
|
||||||
|
await Tests.createNote();
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromId("icon-notebooks").waitAndTap();
|
||||||
|
await Tests.fromText("Notebook 1").waitAndTap();
|
||||||
|
await Tests.fromText("Save").waitAndTap();
|
||||||
|
await Tests.fromText("Notebook 1").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Edit notebook title, description", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.navigate("Notebooks");
|
||||||
|
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||||
|
await Tests.createNotebook();
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.fromText("Notebook 1").isVisible();
|
||||||
|
await Tests.fromId(notesnook.ids.notebook.menu).waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromText("Edit notebook").waitAndTap();
|
||||||
|
await Tests.fromId(
|
||||||
|
notesnook.ids.dialogs.notebook.inputs.title
|
||||||
|
).element.typeText(" (Edited)");
|
||||||
|
await Tests.fromId(
|
||||||
|
notesnook.ids.dialogs.notebook.inputs.description
|
||||||
|
).element.clearText();
|
||||||
|
await Tests.fromId(
|
||||||
|
notesnook.ids.dialogs.notebook.inputs.description
|
||||||
|
).element.typeText("Description of Notebook 1 (Edited)");
|
||||||
|
await Tests.fromText("Save").waitAndTap();
|
||||||
|
await Tests.fromText("Notebook 1 (Edited)").isVisible();
|
||||||
|
await Tests.fromText("Description of Notebook 1 (Edited)").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it.skip("Move notebook to trash", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.navigate("Notebooks");
|
||||||
|
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||||
|
await Tests.createNotebook("Notebook 1", false);
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.fromText("Notebook 1").isVisible();
|
||||||
|
await Tests.fromId(notesnook.ids.notebook.menu).waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromText("Move to trash").waitAndTap();
|
||||||
|
await Tests.fromText("Delete").waitAndTap();
|
||||||
|
await Tests.navigate("Trash");
|
||||||
|
await Tests.fromText("Notebook 1").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Move notebook to trash with notes", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
let note = await Tests.createNote();
|
||||||
|
await Tests.navigate("Notebooks");
|
||||||
|
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||||
|
await Tests.createNotebook("Notebook 1", false);
|
||||||
|
await Tests.fromId("listitem.select").waitAndTap();
|
||||||
|
await Tests.fromText("Move selected notes").waitAndTap();
|
||||||
|
await Tests.fromText("Notebook 1").isVisible();
|
||||||
|
await Tests.fromId(notesnook.ids.notebook.menu).waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromText("Move to trash").waitAndTap();
|
||||||
|
await Tests.fromText(
|
||||||
|
"Move all notes in this notebook to trash"
|
||||||
|
).waitAndTap();
|
||||||
|
await Tests.fromText("Delete").waitAndTap();
|
||||||
|
await Tests.navigate("Trash");
|
||||||
|
await Tests.fromText("Notebook 1").isVisible();
|
||||||
|
await Tests.fromText(note.body).isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it.skip("Pin notebook to side menu", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.navigate("Notebooks");
|
||||||
|
await Tests.fromText("Add your first notebook").waitAndTap();
|
||||||
|
await Tests.createNotebook("Notebook 1", false);
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.fromText("Notebook 1").isVisible();
|
||||||
|
await Tests.fromId(notesnook.ids.notebook.menu).waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromText("Add Shortcut").waitAndTap();
|
||||||
|
await Tests.fromId(notesnook.ids.default.header.buttons.left).waitAndTap();
|
||||||
|
await Tests.fromText("Notebook 1").isVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -17,29 +17,17 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { notesnook } from "../test.ids";
|
import { Tests } from "./utils";
|
||||||
import {
|
|
||||||
tapById,
|
|
||||||
visibleByText,
|
|
||||||
createNote,
|
|
||||||
prepare,
|
|
||||||
elementById,
|
|
||||||
sleep,
|
|
||||||
tapByText
|
|
||||||
} from "./utils";
|
|
||||||
|
|
||||||
describe("Search", () => {
|
describe("Search", () => {
|
||||||
it("Search for a note", async () => {
|
it("Search for a note", async () => {
|
||||||
await prepare();
|
await Tests.prepare();
|
||||||
let note = await createNote();
|
let note = await Tests.createNote();
|
||||||
await tapById("icon-search");
|
await Tests.fromId("icon-search").waitAndTap();
|
||||||
await sleep(300);
|
await Tests.fromId("search-input").element.typeText("Test");
|
||||||
await elementById("search-input").typeText("Test");
|
await Tests.fromText(note.body).waitAndTap();
|
||||||
await sleep(1000);
|
|
||||||
await tapByText(note.body);
|
|
||||||
await sleep(1000);
|
|
||||||
await device.pressBack();
|
await device.pressBack();
|
||||||
await device.pressBack();
|
await device.pressBack();
|
||||||
await visibleByText(note.body);
|
await Tests.fromText(note.body).isVisible();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -1,121 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { notesnook } from "../test.ids";
|
|
||||||
import {
|
|
||||||
tapById,
|
|
||||||
visibleByText,
|
|
||||||
createNote,
|
|
||||||
prepare,
|
|
||||||
tapByText,
|
|
||||||
notVisibleByText,
|
|
||||||
sleep,
|
|
||||||
navigate,
|
|
||||||
createNotebook
|
|
||||||
} from "./utils";
|
|
||||||
|
|
||||||
async function sortBy(sorting, elementText = "Default") {
|
|
||||||
await tapByText(elementText);
|
|
||||||
await tapByText(sorting);
|
|
||||||
await device.pressBack();
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("Sort & filter", () => {
|
|
||||||
it("Sort by date-edited/date-created", async () => {
|
|
||||||
await prepare();
|
|
||||||
let webview = web(by.id(notesnook.editor.id));
|
|
||||||
await createNote("Note 1", "Note 1");
|
|
||||||
await sleep(300);
|
|
||||||
await createNote("Note 2", "Note 2");
|
|
||||||
await sleep(300);
|
|
||||||
await tapByText("Note 1");
|
|
||||||
await sleep(500);
|
|
||||||
await expect(webview.element(by.web.className("ProseMirror"))).toExist();
|
|
||||||
await webview.element(by.web.className("ProseMirror")).tap();
|
|
||||||
await webview
|
|
||||||
.element(by.web.className("ProseMirror"))
|
|
||||||
.typeText("Edited ", true);
|
|
||||||
await device.pressBack();
|
|
||||||
await device.pressBack();
|
|
||||||
await sortBy("Date created");
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
//await visibleByText("Note 2");
|
|
||||||
await device.pressBack();
|
|
||||||
await sortBy("Date edited");
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
//await visibleByText("Edited Note 1");
|
|
||||||
await device.pressBack();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Disable grouping", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote("Note 1", "Note 1");
|
|
||||||
await sleep(300);
|
|
||||||
await sortBy("None");
|
|
||||||
await sleep(300);
|
|
||||||
await visibleByText("None");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Group by Abc", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote("Note 1", "Note 1");
|
|
||||||
await sleep(300);
|
|
||||||
await sortBy("Abc");
|
|
||||||
await visibleByText("N");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Group by Year", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote("Note 1", "Note 1");
|
|
||||||
await sleep(300);
|
|
||||||
await sortBy("Year");
|
|
||||||
await sleep(300);
|
|
||||||
await visibleByText("Year");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Group by Week", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote("Note 1", "Note 1");
|
|
||||||
await sleep(300);
|
|
||||||
await sortBy("Week");
|
|
||||||
await sleep(300);
|
|
||||||
await visibleByText("Week");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Group by Month", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote("Note 1", "Note 1");
|
|
||||||
await sleep(300);
|
|
||||||
await sortBy("Month");
|
|
||||||
await sleep(300);
|
|
||||||
await visibleByText("Month");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Compact mode", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote("Note 1", "Note 1");
|
|
||||||
await sleep(300);
|
|
||||||
await tapById("icon-compact-mode");
|
|
||||||
await sleep(300);
|
|
||||||
await notVisibleByText("Note 1");
|
|
||||||
await tapById("icon-compact-mode");
|
|
||||||
await sleep(300);
|
|
||||||
await visibleByText("Note 1");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
93
apps/mobile/e2e/tests/sort.e2e.ts
Normal file
93
apps/mobile/e2e/tests/sort.e2e.ts
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { notesnook } from "../test.ids";
|
||||||
|
import { Tests } from "./utils";
|
||||||
|
|
||||||
|
async function sortBy(sorting: string, elementText = "Default") {
|
||||||
|
await Tests.fromText(elementText).waitAndTap();
|
||||||
|
await Tests.fromText(sorting).waitAndTap();
|
||||||
|
await device.pressBack();
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("Sort & filter", () => {
|
||||||
|
it("Sort by date-edited/date-created", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
let webview = web();
|
||||||
|
await Tests.createNote("Note 1", "Note 1");
|
||||||
|
await Tests.createNote("Note 2", "Note 2");
|
||||||
|
await Tests.fromText("Note 1").waitAndTap();
|
||||||
|
await webview.element(by.web.className("ProseMirror")).tap();
|
||||||
|
await webview
|
||||||
|
.element(by.web.className("ProseMirror"))
|
||||||
|
.typeText("Edited ", true);
|
||||||
|
await device.pressBack();
|
||||||
|
await device.pressBack();
|
||||||
|
await sortBy("Date created");
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await device.pressBack();
|
||||||
|
await sortBy("Date edited");
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await device.pressBack();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Disable grouping", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote("Note 1", "Note 1");
|
||||||
|
await sortBy("None");
|
||||||
|
await Tests.fromText("Default").isNotVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Group by Abc", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote("Note 1", "Note 1");
|
||||||
|
await sortBy("Abc");
|
||||||
|
await Tests.fromText("N").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Group by Year", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote("Note 1", "Note 1");
|
||||||
|
await sortBy("Year");
|
||||||
|
await Tests.fromText("Year").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Group by Week", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote("Note 1", "Note 1");
|
||||||
|
await sortBy("Week");
|
||||||
|
await Tests.fromText("Week").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Group by Month", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote("Note 1", "Note 1");
|
||||||
|
await sortBy("Month");
|
||||||
|
await Tests.fromText("Month").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Compact mode", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote("Note 1", "Note 1");
|
||||||
|
await Tests.fromId("icon-compact-mode").waitAndTap();
|
||||||
|
await Tests.fromText("Note 1").isNotVisible();
|
||||||
|
await Tests.fromId("icon-compact-mode").waitAndTap();
|
||||||
|
await Tests.fromText("Note 1").isVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,103 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { notesnook } from "../test.ids";
|
|
||||||
import {
|
|
||||||
navigate,
|
|
||||||
tapById,
|
|
||||||
visibleByText,
|
|
||||||
createNote,
|
|
||||||
prepare,
|
|
||||||
elementById,
|
|
||||||
tapByText,
|
|
||||||
notVisibleByText,
|
|
||||||
sleep
|
|
||||||
} from "./utils";
|
|
||||||
|
|
||||||
describe("Tags", () => {
|
|
||||||
it("Tag a note", async () => {
|
|
||||||
await prepare();
|
|
||||||
let note = await createNote();
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
await tapByText("Add tags");
|
|
||||||
await elementById("tag-input").typeText("testtag");
|
|
||||||
await tapByText('Add "#testtag"');
|
|
||||||
await visibleByText("#testtag");
|
|
||||||
await device.pressBack();
|
|
||||||
await device.pressBack();
|
|
||||||
await navigate("Tags");
|
|
||||||
await tapByText("#testtag");
|
|
||||||
await visibleByText(note.body);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Untag a note", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote();
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
await tapByText("Add tags");
|
|
||||||
await elementById("tag-input").typeText("testtag");
|
|
||||||
await tapByText('Add "#testtag"');
|
|
||||||
await visibleByText("#testtag");
|
|
||||||
await tapByText("#testtag");
|
|
||||||
await device.pressBack();
|
|
||||||
await device.pressBack();
|
|
||||||
await notVisibleByText("#testtag");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Creat shortcut of a tag", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote();
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
await tapByText("Add tags");
|
|
||||||
await elementById("tag-input").typeText("testtag");
|
|
||||||
await tapByText('Add "#testtag"');
|
|
||||||
await visibleByText("#testtag");
|
|
||||||
await device.pressBack();
|
|
||||||
await device.pressBack();
|
|
||||||
await navigate("Tags");
|
|
||||||
await sleep(500);
|
|
||||||
await tapById(notesnook.ids.tag.menu);
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Add Shortcut");
|
|
||||||
let menu = elementById(notesnook.ids.default.header.buttons.left);
|
|
||||||
await menu.tap();
|
|
||||||
await visibleByText("#testtag");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Rename a tag", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote();
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
await tapByText("Add tags");
|
|
||||||
await elementById("tag-input").typeText("testtag");
|
|
||||||
await tapByText('Add "#testtag"');
|
|
||||||
await visibleByText("#testtag");
|
|
||||||
await device.pressBack();
|
|
||||||
await device.pressBack();
|
|
||||||
await navigate("Tags");
|
|
||||||
await tapById(notesnook.ids.tag.menu);
|
|
||||||
await sleep(500);
|
|
||||||
await tapByText("Rename tag");
|
|
||||||
await sleep(500);
|
|
||||||
await elementById("input-value").clearText();
|
|
||||||
await elementById("input-value").typeText("testtag_edited");
|
|
||||||
await tapByText("Save");
|
|
||||||
await visibleByText("#testtag_edited");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
95
apps/mobile/e2e/tests/tag.e2e.ts
Normal file
95
apps/mobile/e2e/tests/tag.e2e.ts
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { notesnook } from "../test.ids";
|
||||||
|
import { Tests } from "./utils";
|
||||||
|
|
||||||
|
describe("Tags", () => {
|
||||||
|
it("Tag a note", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
let note = await Tests.createNote();
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromText("Add tag").waitAndTap();
|
||||||
|
await Tests.fromId("tag-input").element.typeText("testtag");
|
||||||
|
await Tests.fromText('Add "#testtag"').waitAndTap();
|
||||||
|
await Tests.fromText("#testtag").isVisible();
|
||||||
|
await device.pressBack();
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.navigate("Tags");
|
||||||
|
await Tests.fromText("#testtag").waitAndTap();
|
||||||
|
await Tests.fromText(note.body).isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Untag a note", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote();
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromText("Add tag").waitAndTap();
|
||||||
|
await Tests.fromId("tag-input").element.typeText("testtag");
|
||||||
|
await Tests.fromText('Add "#testtag"').waitAndTap();
|
||||||
|
await Tests.fromText("#testtag").isVisible();
|
||||||
|
await Tests.fromText("#testtag").waitAndTap();
|
||||||
|
await device.pressBack();
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.fromText("#testtag").isNotVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Create shortcut of a tag", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote();
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromText("Add tag").waitAndTap();
|
||||||
|
await Tests.fromId("tag-input").element.typeText("testtag");
|
||||||
|
await Tests.fromText('Add "#testtag"').waitAndTap();
|
||||||
|
await Tests.fromText("#testtag").isVisible();
|
||||||
|
await device.pressBack();
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.navigate("Tags");
|
||||||
|
await Tests.fromId(notesnook.ids.tag.menu).waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromText("Add shortcut").waitAndTap();
|
||||||
|
await Tests.fromId(notesnook.ids.default.header.buttons.left).waitAndTap();
|
||||||
|
await Tests.fromText("testtag").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Rename a tag", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote();
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromText("Add tag").waitAndTap();
|
||||||
|
await Tests.fromId("tag-input").element.typeText("testtag");
|
||||||
|
await Tests.fromText('Add "#testtag"').waitAndTap();
|
||||||
|
await Tests.fromText("#testtag").isVisible();
|
||||||
|
await device.pressBack();
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.navigate("Tags");
|
||||||
|
await Tests.fromId(notesnook.ids.tag.menu).waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromText("Rename").waitAndTap();
|
||||||
|
await Tests.sleep(100);
|
||||||
|
await Tests.fromId("input-value").element.clearText();
|
||||||
|
await Tests.fromId("input-value").element.typeText("testtag_edited");
|
||||||
|
await Tests.fromText("Save").waitAndTap();
|
||||||
|
await Tests.fromText("#testtag_edited").isVisible();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,166 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { notesnook } from "../test.ids";
|
|
||||||
import { readFileSync } from "fs";
|
|
||||||
import { expect as jestExpect } from "@jest/globals";
|
|
||||||
import { toMatchImageSnapshot } from "jest-image-snapshot";
|
|
||||||
import { device as _device } from "detox";
|
|
||||||
jestExpect.extend({ toMatchImageSnapshot });
|
|
||||||
|
|
||||||
const sleep = (duration) =>
|
|
||||||
new Promise((resolve) =>
|
|
||||||
setTimeout(() => {
|
|
||||||
resolve();
|
|
||||||
}, duration)
|
|
||||||
);
|
|
||||||
|
|
||||||
async function LaunchApp() {
|
|
||||||
await waitFor(element(by.id(notesnook.ids.default.root)))
|
|
||||||
.toBeVisible()
|
|
||||||
.withTimeout(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
function elementById(id) {
|
|
||||||
return element(by.id(id)).atIndex(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function elementByText(text) {
|
|
||||||
return element(by.text(text)).atIndex(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function tapById(id) {
|
|
||||||
await elementById(id).tap();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function tapByText(text) {
|
|
||||||
await elementByText(text).tap();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function visibleByText(text) {
|
|
||||||
await expect(elementByText(text)).toBeVisible();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function visibleById(id) {
|
|
||||||
await expect(elementById(id)).toBeVisible();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function notVisibleById(id) {
|
|
||||||
await expect(elementById(id)).not.toBeVisible();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function notVisibleByText(text) {
|
|
||||||
await expect(elementByText(text)).not.toBeVisible();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function exitEditor() {
|
|
||||||
await _device.pressBack();
|
|
||||||
await _device.pressBack();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createNote(_title, _body) {
|
|
||||||
let title = _title || "Test note description that ";
|
|
||||||
let body =
|
|
||||||
_body ||
|
|
||||||
"Test note description that is very long and should not fit in text.";
|
|
||||||
await tapById(notesnook.buttons.add);
|
|
||||||
let webview = web(by.id(notesnook.editor.id));
|
|
||||||
await expect(webview.element(by.web.className("ProseMirror"))).toExist();
|
|
||||||
await webview.element(by.web.className("ProseMirror")).tap();
|
|
||||||
await webview.element(by.web.className("ProseMirror")).typeText(body, true);
|
|
||||||
await exitEditor();
|
|
||||||
await waitFor(element(by.text(body)))
|
|
||||||
.toBeVisible()
|
|
||||||
.withTimeout(500);
|
|
||||||
|
|
||||||
return { title, body };
|
|
||||||
}
|
|
||||||
|
|
||||||
async function openSideMenu() {
|
|
||||||
let menu = elementById(notesnook.ids.default.header.buttons.left);
|
|
||||||
await menu.tap();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function navigate(screen) {
|
|
||||||
let menu = elementById(notesnook.ids.default.header.buttons.left);
|
|
||||||
await waitFor(menu).toBeVisible().withTimeout(300);
|
|
||||||
await menu.tap();
|
|
||||||
|
|
||||||
await waitFor(elementByText(screen)).toBeVisible().withTimeout(300);
|
|
||||||
await elementByText(screen).tap();
|
|
||||||
}
|
|
||||||
|
|
||||||
const testvars = {
|
|
||||||
isFirstTest: true
|
|
||||||
};
|
|
||||||
|
|
||||||
async function prepare() {
|
|
||||||
await device.disableSynchronization();
|
|
||||||
if (testvars.isFirstTest) {
|
|
||||||
testvars.isFirstTest = false;
|
|
||||||
return await LaunchApp();
|
|
||||||
}
|
|
||||||
await device.reverseTcpPort(8081);
|
|
||||||
await device.uninstallApp();
|
|
||||||
await device.installApp();
|
|
||||||
await device.launchApp({ newInstance: true });
|
|
||||||
await LaunchApp();
|
|
||||||
}
|
|
||||||
|
|
||||||
async function matchSnapshot(element, name) {
|
|
||||||
let path = await element.takeScreenshot(name);
|
|
||||||
const bitmapBuffer = readFileSync(path);
|
|
||||||
jestExpect(bitmapBuffer).toMatchImageSnapshot({
|
|
||||||
failureThreshold: 200,
|
|
||||||
failureThresholdType: "pixel"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createNotebook(title = "Notebook 1", description = true) {
|
|
||||||
await elementById(notesnook.ids.dialogs.notebook.inputs.title).typeText(
|
|
||||||
title
|
|
||||||
);
|
|
||||||
if (description) {
|
|
||||||
await elementById(
|
|
||||||
notesnook.ids.dialogs.notebook.inputs.description
|
|
||||||
).typeText(`Description of ${title}`);
|
|
||||||
}
|
|
||||||
await tapByText("Add");
|
|
||||||
await sleep(300);
|
|
||||||
}
|
|
||||||
|
|
||||||
export {
|
|
||||||
matchSnapshot,
|
|
||||||
createNotebook,
|
|
||||||
prepare,
|
|
||||||
LaunchApp,
|
|
||||||
createNote,
|
|
||||||
navigate,
|
|
||||||
openSideMenu,
|
|
||||||
notVisibleById,
|
|
||||||
notVisibleByText,
|
|
||||||
visibleById,
|
|
||||||
visibleByText,
|
|
||||||
tapById,
|
|
||||||
tapByText,
|
|
||||||
elementByText,
|
|
||||||
elementById,
|
|
||||||
sleep,
|
|
||||||
exitEditor
|
|
||||||
};
|
|
||||||
149
apps/mobile/e2e/tests/utils.ts
Normal file
149
apps/mobile/e2e/tests/utils.ts
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { expect as jestExpect } from "@jest/globals";
|
||||||
|
import { device as _device, expect } from "detox";
|
||||||
|
import { readFileSync } from "fs";
|
||||||
|
import { toMatchImageSnapshot } from "jest-image-snapshot";
|
||||||
|
import type { RouteName } from "../../app/stores/use-navigation-store";
|
||||||
|
import { notesnook } from "../test.ids";
|
||||||
|
jestExpect.extend({ toMatchImageSnapshot });
|
||||||
|
|
||||||
|
const testvars = {
|
||||||
|
isFirstTest: true
|
||||||
|
};
|
||||||
|
|
||||||
|
class Element {
|
||||||
|
element: Detox.NativeElement;
|
||||||
|
constructor(public type: "id" | "text", public value: string) {
|
||||||
|
if (type == "id") {
|
||||||
|
this.element = element(by.id(value)).atIndex(0);
|
||||||
|
} else {
|
||||||
|
this.element = element(by.text(value)).atIndex(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isVisible(timeout?: number) {
|
||||||
|
return waitFor(this.element)
|
||||||
|
.toBeVisible()
|
||||||
|
.withTimeout(timeout || 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
isNotVisible(timeout?: number) {
|
||||||
|
return waitFor(this.element)
|
||||||
|
.not.toBeVisible()
|
||||||
|
.withTimeout(timeout || 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
async waitAndTap(timeout?: number) {
|
||||||
|
await waitFor(this.element)
|
||||||
|
.toBeVisible()
|
||||||
|
.withTimeout(timeout || 500);
|
||||||
|
await this.element.tap();
|
||||||
|
}
|
||||||
|
|
||||||
|
tap(point?: Detox.Point2D): Promise<void> {
|
||||||
|
return this.element.tap(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromId(id: string) {
|
||||||
|
return new Element("id", id);
|
||||||
|
}
|
||||||
|
static fromText(text: string) {
|
||||||
|
return new Element("text", text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Tests = {
|
||||||
|
awaitLaunch: async () => {
|
||||||
|
await waitFor(element(by.id(notesnook.ids.default.root)))
|
||||||
|
.toBeVisible()
|
||||||
|
.withTimeout(500);
|
||||||
|
},
|
||||||
|
sleep: (duration: number) => {
|
||||||
|
return new Promise((resolve) =>
|
||||||
|
setTimeout(() => {
|
||||||
|
resolve(undefined);
|
||||||
|
}, duration)
|
||||||
|
);
|
||||||
|
},
|
||||||
|
fromId: Element.fromId,
|
||||||
|
fromText: Element.fromText,
|
||||||
|
async exitEditor() {
|
||||||
|
await _device.pressBack();
|
||||||
|
await _device.pressBack();
|
||||||
|
},
|
||||||
|
async createNote(_title?: string, _body?: string) {
|
||||||
|
let title = _title || "Test note description that ";
|
||||||
|
let body =
|
||||||
|
_body ||
|
||||||
|
"Test note description that is very long and should not fit in text.";
|
||||||
|
await Tests.fromId(notesnook.buttons.add).tap();
|
||||||
|
await expect(web().element(by.web.className("ProseMirror"))).toExist();
|
||||||
|
// await web().element(by.web.className("ProseMirror")).tap();
|
||||||
|
await web().element(by.web.className("ProseMirror")).typeText(body, true);
|
||||||
|
await Tests.exitEditor();
|
||||||
|
await Tests.fromText(body).isVisible();
|
||||||
|
return { title, body };
|
||||||
|
},
|
||||||
|
async navigate(screen: RouteName | ({} & string)) {
|
||||||
|
let menu = Tests.fromId(notesnook.ids.default.header.buttons.left);
|
||||||
|
await menu.waitAndTap();
|
||||||
|
await Tests.fromText(screen).waitAndTap();
|
||||||
|
},
|
||||||
|
async openSideMenu() {
|
||||||
|
await Tests.fromId(notesnook.ids.default.header.buttons.left).waitAndTap();
|
||||||
|
},
|
||||||
|
async prepare() {
|
||||||
|
await device.disableSynchronization();
|
||||||
|
if (testvars.isFirstTest) {
|
||||||
|
testvars.isFirstTest = false;
|
||||||
|
return await Tests.awaitLaunch();
|
||||||
|
}
|
||||||
|
await device.reverseTcpPort(8081);
|
||||||
|
await device.uninstallApp();
|
||||||
|
await device.installApp();
|
||||||
|
await device.launchApp({ newInstance: true });
|
||||||
|
await Tests.awaitLaunch();
|
||||||
|
},
|
||||||
|
async createNotebook(title = "Notebook 1", description = true) {
|
||||||
|
await Tests.sleep(1000);
|
||||||
|
const titleInput = Tests.fromId(
|
||||||
|
notesnook.ids.dialogs.notebook.inputs.title
|
||||||
|
);
|
||||||
|
await titleInput.isVisible();
|
||||||
|
await titleInput.element.typeText(title);
|
||||||
|
if (description) {
|
||||||
|
await Tests.fromId(
|
||||||
|
notesnook.ids.dialogs.notebook.inputs.description
|
||||||
|
).element.typeText(`Description of ${title}`);
|
||||||
|
}
|
||||||
|
await Tests.fromText("Add").waitAndTap();
|
||||||
|
},
|
||||||
|
async matchSnapshot(element: Element, name: string) {
|
||||||
|
let path = await element.element.takeScreenshot(name);
|
||||||
|
const bitmapBuffer = readFileSync(path);
|
||||||
|
(jestExpect(bitmapBuffer) as any).toMatchImageSnapshot({
|
||||||
|
failureThreshold: 200,
|
||||||
|
failureThresholdType: "pixel"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export { Element, Tests };
|
||||||
@@ -1,145 +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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { notesnook } from "../test.ids";
|
|
||||||
import {
|
|
||||||
tapById,
|
|
||||||
elementById,
|
|
||||||
visibleByText,
|
|
||||||
tapByText,
|
|
||||||
createNote,
|
|
||||||
prepare,
|
|
||||||
visibleById,
|
|
||||||
matchSnapshot,
|
|
||||||
notVisibleById,
|
|
||||||
navigate
|
|
||||||
} from "./utils";
|
|
||||||
import { sleep } from "./utils";
|
|
||||||
|
|
||||||
async function lockNote() {
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
await tapById("icon-lock-unlock");
|
|
||||||
await sleep(1000);
|
|
||||||
await visibleByText("Lock");
|
|
||||||
await elementById(notesnook.ids.dialogs.vault.pwd).typeText("1234");
|
|
||||||
await elementById(notesnook.ids.dialogs.vault.pwdAlt).typeText("1234");
|
|
||||||
await tapByText("Lock");
|
|
||||||
await sleep(500);
|
|
||||||
await visibleById("note-locked-icon");
|
|
||||||
}
|
|
||||||
|
|
||||||
async function removeFromVault() {
|
|
||||||
await tapById(notesnook.listitem.menu);
|
|
||||||
await tapById("icon-lock-unlock");
|
|
||||||
await sleep(1000);
|
|
||||||
await elementById(notesnook.ids.dialogs.vault.pwd).typeText("1234");
|
|
||||||
await tapByText("Unlock");
|
|
||||||
await sleep(1000);
|
|
||||||
await notVisibleById("note-locked-icon");
|
|
||||||
}
|
|
||||||
|
|
||||||
async function openLockedNote(pwd) {
|
|
||||||
await tapById(notesnook.ids.note.get(1));
|
|
||||||
await sleep(1000);
|
|
||||||
await visibleByText("Open");
|
|
||||||
await elementById(notesnook.ids.dialogs.vault.pwd).typeText(pwd || "1234");
|
|
||||||
await tapByText("Open");
|
|
||||||
await sleep(3000);
|
|
||||||
await matchSnapshot(elementById("editor-wrapper"), "note-after-vault-unlock");
|
|
||||||
}
|
|
||||||
|
|
||||||
async function goToPrivacySecuritySettings() {
|
|
||||||
await navigate("Settings");
|
|
||||||
await tapByText("Vault");
|
|
||||||
await sleep(500);
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("VAULT", () => {
|
|
||||||
it("Create vault from settings", async () => {
|
|
||||||
await prepare();
|
|
||||||
await goToPrivacySecuritySettings();
|
|
||||||
await tapByText("Create vault");
|
|
||||||
await elementById(notesnook.ids.dialogs.vault.pwd).typeText("1234");
|
|
||||||
await elementById(notesnook.ids.dialogs.vault.pwdAlt).typeText("1234");
|
|
||||||
await tapByText("Create");
|
|
||||||
await sleep(500);
|
|
||||||
await visibleByText("Clear vault");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Change vault password", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote();
|
|
||||||
await lockNote();
|
|
||||||
await goToPrivacySecuritySettings();
|
|
||||||
await tapByText("Change vault password");
|
|
||||||
await elementById(notesnook.ids.dialogs.vault.pwd).typeText("1234");
|
|
||||||
await elementById(notesnook.ids.dialogs.vault.changePwd).typeText("2362");
|
|
||||||
await tapByText("Change");
|
|
||||||
await sleep(2000);
|
|
||||||
await device.pressBack();
|
|
||||||
await device.pressBack();
|
|
||||||
await device.pressBack();
|
|
||||||
await openLockedNote("2362");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Delete vault", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote();
|
|
||||||
await lockNote();
|
|
||||||
await goToPrivacySecuritySettings();
|
|
||||||
await tapByText("Delete vault");
|
|
||||||
await elementById(notesnook.ids.dialogs.vault.pwd).typeText("1234");
|
|
||||||
await tapByText("Delete");
|
|
||||||
await sleep(500);
|
|
||||||
await visibleByText("Create vault");
|
|
||||||
await device.pressBack();
|
|
||||||
await device.pressBack();
|
|
||||||
await visibleById(notesnook.listitem.menu);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Delete vault with locked notes", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote();
|
|
||||||
await lockNote();
|
|
||||||
await goToPrivacySecuritySettings();
|
|
||||||
await tapByText("Delete vault");
|
|
||||||
await elementById(notesnook.ids.dialogs.vault.pwd).typeText("1234");
|
|
||||||
await tapByText("Delete all notes");
|
|
||||||
await tapByText("Delete");
|
|
||||||
await sleep(500);
|
|
||||||
await visibleByText("Create vault");
|
|
||||||
await device.pressBack();
|
|
||||||
await device.pressBack();
|
|
||||||
await notVisibleById(notesnook.listitem.menu);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Add a note to vault", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote();
|
|
||||||
await lockNote();
|
|
||||||
await openLockedNote();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Remove note from vault", async () => {
|
|
||||||
await prepare();
|
|
||||||
await createNote();
|
|
||||||
await lockNote();
|
|
||||||
await removeFromVault();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
143
apps/mobile/e2e/tests/vault.e2e.ts
Normal file
143
apps/mobile/e2e/tests/vault.e2e.ts
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
import { expect } from "detox";
|
||||||
|
import { notesnook } from "../test.ids";
|
||||||
|
import { Tests } from "./utils";
|
||||||
|
|
||||||
|
async function lockNote() {
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromId("icon-lock-unlock").waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromText("Lock").isVisible();
|
||||||
|
await Tests.fromId(notesnook.ids.dialogs.vault.pwd).element.typeText("1234");
|
||||||
|
await Tests.fromId(notesnook.ids.dialogs.vault.pwdAlt).element.typeText(
|
||||||
|
"1234"
|
||||||
|
);
|
||||||
|
await Tests.fromText("Lock").waitAndTap();
|
||||||
|
await Tests.fromId("note-locked-icon").isVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function removeFromVault() {
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromId("icon-lock-unlock").waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await Tests.fromId(notesnook.ids.dialogs.vault.pwd).element.typeText("1234");
|
||||||
|
await Tests.fromText("Unlock").waitAndTap();
|
||||||
|
await Tests.fromId("note-locked-icon").isNotVisible();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function openLockedNote(pwd?: string) {
|
||||||
|
await Tests.fromId(notesnook.ids.note.get(0)).waitAndTap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await web()
|
||||||
|
.element(by.web.name("password"))
|
||||||
|
.typeText(pwd || "1234", false);
|
||||||
|
await web().element(by.web.className("unlock-note")).tap();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await expect(web().element(by.web.className("unlock-note"))).not.toExist();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function goToPrivacySecuritySettings() {
|
||||||
|
await Tests.navigate("Settings");
|
||||||
|
await Tests.fromText("Vault").waitAndTap();
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("VAULT", () => {
|
||||||
|
it("Create vault from settings", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await goToPrivacySecuritySettings();
|
||||||
|
await Tests.fromText("Create vault").waitAndTap();
|
||||||
|
await Tests.fromId(notesnook.ids.dialogs.vault.pwd).element.typeText(
|
||||||
|
"1234"
|
||||||
|
);
|
||||||
|
await Tests.fromId(notesnook.ids.dialogs.vault.pwdAlt).element.typeText(
|
||||||
|
"1234"
|
||||||
|
);
|
||||||
|
await Tests.fromText("Create").waitAndTap();
|
||||||
|
await Tests.fromText("Clear vault").isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Change vault password", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote();
|
||||||
|
await lockNote();
|
||||||
|
await goToPrivacySecuritySettings();
|
||||||
|
await Tests.fromText("Change vault password").waitAndTap();
|
||||||
|
await Tests.fromId(notesnook.ids.dialogs.vault.pwd).element.typeText(
|
||||||
|
"1234"
|
||||||
|
);
|
||||||
|
await Tests.fromId(notesnook.ids.dialogs.vault.changePwd).element.typeText(
|
||||||
|
"2362"
|
||||||
|
);
|
||||||
|
await Tests.fromText("Change").waitAndTap();
|
||||||
|
await device.pressBack();
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.sleep(500);
|
||||||
|
await openLockedNote("2362");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Delete vault", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote();
|
||||||
|
await lockNote();
|
||||||
|
await goToPrivacySecuritySettings();
|
||||||
|
await Tests.fromText("Delete vault").waitAndTap();
|
||||||
|
await Tests.fromId(notesnook.ids.dialogs.vault.pwd).element.typeText(
|
||||||
|
"1234"
|
||||||
|
);
|
||||||
|
await Tests.fromText("Delete").waitAndTap();
|
||||||
|
await Tests.fromText("Create vault").isVisible();
|
||||||
|
await device.pressBack();
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).isVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Delete vault with locked notes", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote();
|
||||||
|
await lockNote();
|
||||||
|
await goToPrivacySecuritySettings();
|
||||||
|
await Tests.fromText("Delete vault").waitAndTap();
|
||||||
|
await Tests.fromId(notesnook.ids.dialogs.vault.pwd).element.typeText(
|
||||||
|
"1234"
|
||||||
|
);
|
||||||
|
await Tests.fromText("Delete notes in this vault").waitAndTap();
|
||||||
|
await Tests.fromText("Delete").waitAndTap();
|
||||||
|
await Tests.fromText("Create vault").isVisible();
|
||||||
|
await device.pressBack();
|
||||||
|
await device.pressBack();
|
||||||
|
await Tests.fromId(notesnook.listitem.menu).isNotVisible();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Add a note to vault", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote();
|
||||||
|
await lockNote();
|
||||||
|
await openLockedNote();
|
||||||
|
});
|
||||||
|
|
||||||
|
it.only("Remove note from vault", async () => {
|
||||||
|
await Tests.prepare();
|
||||||
|
await Tests.createNote();
|
||||||
|
await lockNote();
|
||||||
|
await removeFromVault();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -52,7 +52,7 @@ module.exports = {
|
|||||||
emulator: {
|
emulator: {
|
||||||
type: 'android.emulator',
|
type: 'android.emulator',
|
||||||
device: {
|
device: {
|
||||||
avdName: 'Pixel_5_API_31'
|
avdName: 'Pixel_5_API_34'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ammarahmed/notifee-react-native": "7.4.7",
|
"@ammarahmed/notifee-react-native": "7.4.7",
|
||||||
"@ammarahmed/react-native-share-extension": "^3.0.0",
|
|
||||||
"@ammarahmed/react-native-sodium": "1.5.4",
|
|
||||||
"@bam.tech/react-native-image-resizer": "3.0.5",
|
"@bam.tech/react-native-image-resizer": "3.0.5",
|
||||||
"@callstack/repack": "^4.1.1",
|
"@callstack/repack": "^4.1.1",
|
||||||
"@react-native-clipboard/clipboard": "^1.9.0",
|
"@react-native-clipboard/clipboard": "^1.9.0",
|
||||||
@@ -73,7 +71,10 @@
|
|||||||
"react-native-url-polyfill": "^2.0.0",
|
"react-native-url-polyfill": "^2.0.0",
|
||||||
"react-native-screenguard": "^1.0.0",
|
"react-native-screenguard": "^1.0.0",
|
||||||
"@formatjs/intl-locale": "4.0.0",
|
"@formatjs/intl-locale": "4.0.0",
|
||||||
"@formatjs/intl-pluralrules": "5.2.14"
|
"@formatjs/intl-pluralrules": "5.2.14",
|
||||||
|
"detox": "^20.27.6",
|
||||||
|
"@ammarahmed/react-native-share-extension": "^2.6.0",
|
||||||
|
"@ammarahmed/react-native-sodium": "1.5.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.0",
|
"@babel/core": "^7.20.0",
|
||||||
@@ -86,7 +87,6 @@
|
|||||||
"@react-native/metro-config": "0.74.86",
|
"@react-native/metro-config": "0.74.86",
|
||||||
"@tsconfig/react-native": "^3.0.2",
|
"@tsconfig/react-native": "^3.0.2",
|
||||||
"@types/html-to-text": "^8.0.1",
|
"@types/html-to-text": "^8.0.1",
|
||||||
"@types/jest": "^29.2.1",
|
|
||||||
"@types/metro-config": "^0.76.3",
|
"@types/metro-config": "^0.76.3",
|
||||||
"@types/react": "^18.2.6",
|
"@types/react": "^18.2.6",
|
||||||
"@types/react-native": "^0.69.1",
|
"@types/react-native": "^0.69.1",
|
||||||
@@ -98,19 +98,13 @@
|
|||||||
"babel-loader": "^8.2.5",
|
"babel-loader": "^8.2.5",
|
||||||
"babel-plugin-module-resolver": "^4.1.0",
|
"babel-plugin-module-resolver": "^4.1.0",
|
||||||
"babel-plugin-transform-remove-console": "6.9.4",
|
"babel-plugin-transform-remove-console": "6.9.4",
|
||||||
"detox": "^20.11.2",
|
|
||||||
"eslint": "^8.19.0",
|
"eslint": "^8.19.0",
|
||||||
"eslint-config-prettier": "^8.3.0",
|
"eslint-config-prettier": "^8.3.0",
|
||||||
"eslint-plugin-prettier": "^4.0.0",
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
"eslint-plugin-react": "^7.28.0",
|
"eslint-plugin-react": "^7.28.0",
|
||||||
"eslint-plugin-react-native": "^4.0.0",
|
"eslint-plugin-react-native": "^4.0.0",
|
||||||
"eslint-plugin-unused-imports": "^2.0.0",
|
"eslint-plugin-unused-imports": "^2.0.0",
|
||||||
"expect": "^29.6.2",
|
|
||||||
"jest": "^29.6.3",
|
|
||||||
"jest-circus": "^29.6.2",
|
|
||||||
"jest-image-snapshot": "^6.2.0",
|
|
||||||
"@react-native/babel-preset": "0.74.86",
|
"@react-native/babel-preset": "0.74.86",
|
||||||
"pixelmatch": "^5.3.0",
|
|
||||||
"prettier": "2.8.8",
|
"prettier": "2.8.8",
|
||||||
"react-native-actions-shortcuts": "^1.0.1",
|
"react-native-actions-shortcuts": "^1.0.1",
|
||||||
"react-native-bundle-visualizer": "^3.1.1",
|
"react-native-bundle-visualizer": "^3.1.1",
|
||||||
@@ -118,10 +112,16 @@
|
|||||||
"react-refresh": "0.14.0",
|
"react-refresh": "0.14.0",
|
||||||
"react-test-renderer": "18.2.0",
|
"react-test-renderer": "18.2.0",
|
||||||
"terser-webpack-plugin": "^5.3.5",
|
"terser-webpack-plugin": "^5.3.5",
|
||||||
"ts-jest": "^29.1.1",
|
|
||||||
"webpack-cli": "^5.1.4",
|
"webpack-cli": "^5.1.4",
|
||||||
"webpack": "^5.88.2",
|
"webpack": "^5.88.2",
|
||||||
"metro-react-native-babel-preset": "0.77.0",
|
"metro-react-native-babel-preset": "0.77.0",
|
||||||
"acorn-import-attributes": "1.9.5"
|
"acorn-import-attributes": "1.9.5",
|
||||||
|
"expect": "^29.7.0",
|
||||||
|
"jest": "^29.7.0",
|
||||||
|
"jest-circus": "^29.7.0",
|
||||||
|
"jest-image-snapshot": "^6.4.0",
|
||||||
|
"ts-jest": "^29.2.5",
|
||||||
|
"pixelmatch": "^6.0.0",
|
||||||
|
"@types/jest": "^29.5.14"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
515
apps/mobile/package-lock.json
generated
515
apps/mobile/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
|||||||
diff --git a/node_modules/react-native-actions-shortcuts/android/build.gradle b/node_modules/react-native-actions-shortcuts/android/build.gradle
|
diff --git a/node_modules/react-native-actions-shortcuts/android/build.gradle b/node_modules/react-native-actions-shortcuts/android/build.gradle
|
||||||
index 19bd311..d15cdaf 100644
|
index 19bd311..bc37238 100644
|
||||||
--- a/node_modules/react-native-actions-shortcuts/android/build.gradle
|
--- a/node_modules/react-native-actions-shortcuts/android/build.gradle
|
||||||
+++ b/node_modules/react-native-actions-shortcuts/android/build.gradle
|
+++ b/node_modules/react-native-actions-shortcuts/android/build.gradle
|
||||||
@@ -29,7 +29,7 @@ android {
|
@@ -29,7 +29,7 @@ android {
|
||||||
@@ -7,7 +7,7 @@ index 19bd311..d15cdaf 100644
|
|||||||
buildToolsVersion getExtOrDefault('buildToolsVersion')
|
buildToolsVersion getExtOrDefault('buildToolsVersion')
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
- minSdkVersion 16
|
- minSdkVersion 16
|
||||||
+ minSdkVersion 21
|
+ minSdkVersion getExtOrDefault('minSdkVersion')
|
||||||
targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
|
targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
diff --git a/node_modules/react-native-fingerprint-scanner/android/build.gradle b/node_modules/react-native-fingerprint-scanner/android/build.gradle
|
||||||
|
index eaf3829..6c392ba 100644
|
||||||
|
--- a/node_modules/react-native-fingerprint-scanner/android/build.gradle
|
||||||
|
+++ b/node_modules/react-native-fingerprint-scanner/android/build.gradle
|
||||||
|
@@ -49,5 +49,5 @@ dependencies {
|
||||||
|
// 1.2.3 is the minimum version compatible with androidx.
|
||||||
|
// See https://github.com/uccmawei/FingerprintIdentify/issues/74
|
||||||
|
// (translation https://translate.google.com/translate?sl=zh-CN&tl=en&u=https://github.com/uccmawei/FingerprintIdentify/issues/74)
|
||||||
|
- implementation "com.wei.android.lib:fingerprintidentify:${safeExtGet("fingerprintidentify", "1.2.6")}"
|
||||||
|
+ implementation "com.github.uccmawei:FingerprintIdentify:1.2.6"
|
||||||
|
}
|
||||||
@@ -39,7 +39,7 @@ index 0ccfd23..7771e6f 100644
|
|||||||
s.preserve_paths = 'LICENSE', 'package.json'
|
s.preserve_paths = 'LICENSE', 'package.json'
|
||||||
s.source_files = '**/*.{h,m}'
|
s.source_files = '**/*.{h,m}'
|
||||||
diff --git a/node_modules/react-native-tooltips/android/build.gradle b/node_modules/react-native-tooltips/android/build.gradle
|
diff --git a/node_modules/react-native-tooltips/android/build.gradle b/node_modules/react-native-tooltips/android/build.gradle
|
||||||
index 978045f..401b458 100644
|
index 978045f..59c64f1 100644
|
||||||
--- a/node_modules/react-native-tooltips/android/build.gradle
|
--- a/node_modules/react-native-tooltips/android/build.gradle
|
||||||
+++ b/node_modules/react-native-tooltips/android/build.gradle
|
+++ b/node_modules/react-native-tooltips/android/build.gradle
|
||||||
@@ -3,8 +3,9 @@ buildscript {
|
@@ -3,8 +3,9 @@ buildscript {
|
||||||
@@ -53,24 +53,36 @@ index 978045f..401b458 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -15,12 +16,12 @@ buildscript {
|
@@ -14,18 +15,19 @@ buildscript {
|
||||||
|
|
||||||
apply plugin: 'com.android.library'
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
android {
|
-android {
|
||||||
- compileSdkVersion 29
|
- compileSdkVersion 29
|
||||||
- buildToolsVersion '29.0.2'
|
- buildToolsVersion '29.0.2'
|
||||||
+ compileSdkVersion 31
|
|
||||||
+ buildToolsVersion '31.0.0'
|
|
||||||
|
|
||||||
|
+def safeExtGet(prop, fallback) {
|
||||||
|
+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+android {
|
||||||
|
+ compileSdkVersion safeExtGet('compileSdkVersion', 29)
|
||||||
|
+ buildToolsVersion safeExtGet('buildToolsVersion', '29.0.2')
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
- minSdkVersion 16
|
- minSdkVersion 16
|
||||||
- targetSdkVersion 29
|
- targetSdkVersion 29
|
||||||
+ minSdkVersion 21
|
+ minSdkVersion safeExtGet('minSdkVersion', 21)
|
||||||
+ targetSdkVersion 31
|
+ targetSdkVersion safeExtGet('targetSdkVersion', 29)
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
- versionName "1.0"
|
||||||
|
- }
|
||||||
|
- lintOptions {
|
||||||
|
- abortOnError false
|
||||||
|
+ versionName "0.1"
|
||||||
}
|
}
|
||||||
@@ -36,5 +37,5 @@ repositories {
|
}
|
||||||
|
|
||||||
|
@@ -36,5 +38,5 @@ repositories {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.facebook.react:react-native:+'
|
implementation 'com.facebook.react:react-native:+'
|
||||||
@@ -104,7 +116,7 @@ index fb96466..75a6fdb 100644
|
|||||||
|
|
||||||
@interface TooltipDelegate : NSObject <SexyTooltipDelegate>
|
@interface TooltipDelegate : NSObject <SexyTooltipDelegate>
|
||||||
|
|
||||||
@@ -7,9 +9,15 @@ @interface TooltipDelegate : NSObject <SexyTooltipDelegate>
|
@@ -7,9 +9,15 @@
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation TooltipDelegate
|
@implementation TooltipDelegate
|
||||||
@@ -120,7 +132,7 @@ index fb96466..75a6fdb 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -17,77 +25,120 @@ - (void)tooltipDidDismiss:(SexyTooltip *)tooltip {
|
@@ -17,77 +25,120 @@
|
||||||
|
|
||||||
@implementation RNTooltips
|
@implementation RNTooltips
|
||||||
|
|
||||||
|
|||||||
@@ -646,6 +646,7 @@ const Tiptap = ({
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
className="unlock-note"
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: colors.primary.accent,
|
backgroundColor: colors.primary.accent,
|
||||||
borderRadius: 5,
|
borderRadius: 5,
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -424,12 +424,11 @@ $headline$: Use starting line of the note as title.`,
|
|||||||
other: ""
|
other: ""
|
||||||
}),
|
}),
|
||||||
|
|
||||||
createVault: () => t`Create Vault`,
|
createVault: () => t`Create vault`,
|
||||||
createVaultDesc: () =>
|
createVaultDesc: () => t`A vault stores your notes in a encrypted storage.`,
|
||||||
t`A vault stores your notes in a password-encrypted storage.`,
|
vaultFingerprintUnlock: () => t`Vault fingerprint unlock`,
|
||||||
vaultFingerprintUnlock: () => t`Vault Fingerprint Unlock`,
|
revokeVaultFingerprintUnlock: () => t`Revoke vault fingerprint unlock`,
|
||||||
revokeVaultFingerprintUnlock: () => t`Revoke Vault Fingerprint Unlock`,
|
changeVaultPassword: () => t`Change vault password`,
|
||||||
changeVaultPassword: () => t`Change Vault Password`,
|
|
||||||
deleteNote: () => doActions.delete.note(1),
|
deleteNote: () => doActions.delete.note(1),
|
||||||
shareNote: () => t`Share note`,
|
shareNote: () => t`Share note`,
|
||||||
copyNote: () => t`Copy note`,
|
copyNote: () => t`Copy note`,
|
||||||
|
|||||||
Reference in New Issue
Block a user