1
0
mirror of https://github.com/laurent22/joplin.git synced 2026-01-02 00:08:04 +02:00

Compare commits

...

12 Commits

Author SHA1 Message Date
Laurent Cozic
b686a9b164 tests 2021-05-25 11:25:33 +02:00
Laurent Cozic
853830d8da login 2021-05-24 11:36:24 +02:00
Laurent Cozic
aa9397e9e7 expire tokens 2021-05-21 20:11:26 +02:00
Laurent Cozic
411ce01552 email validation 2021-05-21 19:58:49 +02:00
Laurent Cozic
0f85acf16d Merge branch 'dev' into server_mailer 2021-05-21 17:04:53 +02:00
Laurent Cozic
e94503abbe Tools: Fixed tests 2021-05-21 17:02:56 +02:00
Laurent Cozic
427e32d324 Merge branch 'dev' into server_mailer 2021-05-21 15:20:53 +02:00
Laurent Cozic
f8253cc2f0 Merge branch 'dev' of github.com:laurent22/joplin into dev 2021-05-21 15:17:51 +02:00
Laurent Cozic
2806aa1b19 Tools: Moved lib-specific tests under lib package 2021-05-21 15:17:21 +02:00
小骏
8f57e07279 All: Translation: Update zh_CN.po (#4993) 2021-05-21 00:48:05 -04:00
Laurent Cozic
6a41d43399 email 2021-05-19 19:43:26 +02:00
Laurent Cozic
fa3895452f mailer 2021-05-19 12:31:17 +02:00
135 changed files with 2065 additions and 1469 deletions

View File

@@ -74,75 +74,21 @@ packages/app-cli/app/command-settingschema.js.map
packages/app-cli/app/services/plugins/PluginRunner.d.ts
packages/app-cli/app/services/plugins/PluginRunner.js
packages/app-cli/app/services/plugins/PluginRunner.js.map
packages/app-cli/tests/EnexToMd.d.ts
packages/app-cli/tests/EnexToMd.js
packages/app-cli/tests/EnexToMd.js.map
packages/app-cli/tests/HtmlToMd.d.ts
packages/app-cli/tests/HtmlToMd.js
packages/app-cli/tests/HtmlToMd.js.map
packages/app-cli/tests/InMemoryCache.d.ts
packages/app-cli/tests/InMemoryCache.js
packages/app-cli/tests/InMemoryCache.js.map
packages/app-cli/tests/MdToHtml.d.ts
packages/app-cli/tests/MdToHtml.js
packages/app-cli/tests/MdToHtml.js.map
packages/app-cli/tests/MdToMd.d.ts
packages/app-cli/tests/MdToMd.js
packages/app-cli/tests/MdToMd.js.map
packages/app-cli/tests/Synchronizer.basics.d.ts
packages/app-cli/tests/Synchronizer.basics.js
packages/app-cli/tests/Synchronizer.basics.js.map
packages/app-cli/tests/Synchronizer.conflicts.d.ts
packages/app-cli/tests/Synchronizer.conflicts.js
packages/app-cli/tests/Synchronizer.conflicts.js.map
packages/app-cli/tests/Synchronizer.e2ee.d.ts
packages/app-cli/tests/Synchronizer.e2ee.js
packages/app-cli/tests/Synchronizer.e2ee.js.map
packages/app-cli/tests/Synchronizer.resources.d.ts
packages/app-cli/tests/Synchronizer.resources.js
packages/app-cli/tests/Synchronizer.resources.js.map
packages/app-cli/tests/Synchronizer.revisions.d.ts
packages/app-cli/tests/Synchronizer.revisions.js
packages/app-cli/tests/Synchronizer.revisions.js.map
packages/app-cli/tests/Synchronizer.sharing.d.ts
packages/app-cli/tests/Synchronizer.sharing.js
packages/app-cli/tests/Synchronizer.sharing.js.map
packages/app-cli/tests/Synchronizer.tags.d.ts
packages/app-cli/tests/Synchronizer.tags.js
packages/app-cli/tests/Synchronizer.tags.js.map
packages/app-cli/tests/Synchronizer.tools.d.ts
packages/app-cli/tests/Synchronizer.tools.js
packages/app-cli/tests/Synchronizer.tools.js.map
packages/app-cli/tests/dateTimeFormats.d.ts
packages/app-cli/tests/dateTimeFormats.js
packages/app-cli/tests/dateTimeFormats.js.map
packages/app-cli/tests/file-api-driver.d.ts
packages/app-cli/tests/file-api-driver.js
packages/app-cli/tests/file-api-driver.js.map
packages/app-cli/tests/fsDriver.d.ts
packages/app-cli/tests/fsDriver.js
packages/app-cli/tests/fsDriver.js.map
packages/app-cli/tests/htmlUtils.d.ts
packages/app-cli/tests/htmlUtils.js
packages/app-cli/tests/htmlUtils.js.map
packages/app-cli/tests/markdownUtils.d.ts
packages/app-cli/tests/markdownUtils.js
packages/app-cli/tests/markdownUtils.js.map
packages/app-cli/tests/models_Folder.d.ts
packages/app-cli/tests/models_Folder.js
packages/app-cli/tests/models_Folder.js.map
packages/app-cli/tests/models_Folder.sharing.d.ts
packages/app-cli/tests/models_Folder.sharing.js
packages/app-cli/tests/models_Folder.sharing.js.map
packages/app-cli/tests/models_Note.d.ts
packages/app-cli/tests/models_Note.js
packages/app-cli/tests/models_Note.js.map
packages/app-cli/tests/models_Setting.d.ts
packages/app-cli/tests/models_Setting.js
packages/app-cli/tests/models_Setting.js.map
packages/app-cli/tests/registry.d.ts
packages/app-cli/tests/registry.js
packages/app-cli/tests/registry.js.map
packages/app-cli/tests/services/keychain/KeychainService.d.ts
packages/app-cli/tests/services/keychain/KeychainService.js
packages/app-cli/tests/services/keychain/KeychainService.js.map
packages/app-cli/tests/services/plugins/PluginService.d.ts
packages/app-cli/tests/services/plugins/PluginService.js
packages/app-cli/tests/services/plugins/PluginService.js.map
packages/app-cli/tests/services/plugins/RepositoryApi.d.ts
packages/app-cli/tests/services/plugins/RepositoryApi.js
packages/app-cli/tests/services/plugins/RepositoryApi.js.map
@@ -158,42 +104,6 @@ packages/app-cli/tests/services/plugins/api/JoplinWorkspace.js.map
packages/app-cli/tests/services/plugins/sandboxProxy.d.ts
packages/app-cli/tests/services/plugins/sandboxProxy.js
packages/app-cli/tests/services/plugins/sandboxProxy.js.map
packages/app-cli/tests/services_CommandService.d.ts
packages/app-cli/tests/services_CommandService.js
packages/app-cli/tests/services_CommandService.js.map
packages/app-cli/tests/services_InteropService.d.ts
packages/app-cli/tests/services_InteropService.js
packages/app-cli/tests/services_InteropService.js.map
packages/app-cli/tests/services_InteropService_Exporter_Html.d.ts
packages/app-cli/tests/services_InteropService_Exporter_Html.js
packages/app-cli/tests/services_InteropService_Exporter_Html.js.map
packages/app-cli/tests/services_PluginService.d.ts
packages/app-cli/tests/services_PluginService.js
packages/app-cli/tests/services_PluginService.js.map
packages/app-cli/tests/services_ResourceService.d.ts
packages/app-cli/tests/services_ResourceService.js
packages/app-cli/tests/services_ResourceService.js.map
packages/app-cli/tests/services_SearchEngineUtils.d.ts
packages/app-cli/tests/services_SearchEngineUtils.js
packages/app-cli/tests/services_SearchEngineUtils.js.map
packages/app-cli/tests/services_keychainService.d.ts
packages/app-cli/tests/services_keychainService.js
packages/app-cli/tests/services_keychainService.js.map
packages/app-cli/tests/services_rest_Api.d.ts
packages/app-cli/tests/services_rest_Api.js
packages/app-cli/tests/services_rest_Api.js.map
packages/app-cli/tests/synchronizer_LockHandler.d.ts
packages/app-cli/tests/synchronizer_LockHandler.js
packages/app-cli/tests/synchronizer_LockHandler.js.map
packages/app-cli/tests/synchronizer_MigrationHandler.d.ts
packages/app-cli/tests/synchronizer_MigrationHandler.js
packages/app-cli/tests/synchronizer_MigrationHandler.js.map
packages/app-cli/tests/test-utils-synchronizer.d.ts
packages/app-cli/tests/test-utils-synchronizer.js
packages/app-cli/tests/test-utils-synchronizer.js.map
packages/app-cli/tests/test-utils.d.ts
packages/app-cli/tests/test-utils.js
packages/app-cli/tests/test-utils.js.map
packages/app-desktop/ElectronAppWrapper.d.ts
packages/app-desktop/ElectronAppWrapper.js
packages/app-desktop/ElectronAppWrapper.js.map
@@ -890,6 +800,9 @@ packages/lib/HtmlToMd.js.map
packages/lib/InMemoryCache.d.ts
packages/lib/InMemoryCache.js
packages/lib/InMemoryCache.js.map
packages/lib/InMemoryCache.test.d.ts
packages/lib/InMemoryCache.test.js
packages/lib/InMemoryCache.test.js.map
packages/lib/JoplinDatabase.d.ts
packages/lib/JoplinDatabase.js
packages/lib/JoplinDatabase.js.map
@@ -941,6 +854,9 @@ packages/lib/eventManager.js.map
packages/lib/file-api-driver-joplinServer.d.ts
packages/lib/file-api-driver-joplinServer.js
packages/lib/file-api-driver-joplinServer.js.map
packages/lib/file-api-driver.test.d.ts
packages/lib/file-api-driver.test.js
packages/lib/file-api-driver.test.js.map
packages/lib/file-api.d.ts
packages/lib/file-api.js
packages/lib/file-api.js.map
@@ -950,15 +866,24 @@ packages/lib/fs-driver-base.js.map
packages/lib/fs-driver-node.d.ts
packages/lib/fs-driver-node.js
packages/lib/fs-driver-node.js.map
packages/lib/fsDriver.test.d.ts
packages/lib/fsDriver.test.js
packages/lib/fsDriver.test.js.map
packages/lib/htmlUtils.d.ts
packages/lib/htmlUtils.js
packages/lib/htmlUtils.js.map
packages/lib/htmlUtils.test.d.ts
packages/lib/htmlUtils.test.js
packages/lib/htmlUtils.test.js.map
packages/lib/htmlUtils2.test.d.ts
packages/lib/htmlUtils2.test.js
packages/lib/htmlUtils2.test.js.map
packages/lib/import-enex-md-gen.d.ts
packages/lib/import-enex-md-gen.js
packages/lib/import-enex-md-gen.js.map
packages/lib/import-enex-md-gen.test.d.ts
packages/lib/import-enex-md-gen.test.js
packages/lib/import-enex-md-gen.test.js.map
packages/lib/locale.d.ts
packages/lib/locale.js
packages/lib/locale.js.map
@@ -968,6 +893,9 @@ packages/lib/markdownUtils.js.map
packages/lib/markdownUtils.test.d.ts
packages/lib/markdownUtils.test.js
packages/lib/markdownUtils.test.js.map
packages/lib/markdownUtils2.test.d.ts
packages/lib/markdownUtils2.test.js
packages/lib/markdownUtils2.test.js.map
packages/lib/markupLanguageUtils.d.ts
packages/lib/markupLanguageUtils.js
packages/lib/markupLanguageUtils.js.map
@@ -980,6 +908,12 @@ packages/lib/models/BaseItem.js.map
packages/lib/models/Folder.d.ts
packages/lib/models/Folder.js
packages/lib/models/Folder.js.map
packages/lib/models/Folder.sharing.test.d.ts
packages/lib/models/Folder.sharing.test.js
packages/lib/models/Folder.sharing.test.js.map
packages/lib/models/Folder.test.d.ts
packages/lib/models/Folder.test.js
packages/lib/models/Folder.test.js.map
packages/lib/models/ItemChange.d.ts
packages/lib/models/ItemChange.js
packages/lib/models/ItemChange.js.map
@@ -992,6 +926,9 @@ packages/lib/models/Migration.js.map
packages/lib/models/Note.d.ts
packages/lib/models/Note.js
packages/lib/models/Note.js.map
packages/lib/models/Note.test.d.ts
packages/lib/models/Note.test.js
packages/lib/models/Note.test.js.map
packages/lib/models/NoteResource.d.ts
packages/lib/models/NoteResource.js
packages/lib/models/NoteResource.js.map
@@ -1013,12 +950,18 @@ packages/lib/models/Search.js.map
packages/lib/models/Setting.d.ts
packages/lib/models/Setting.js
packages/lib/models/Setting.js.map
packages/lib/models/Setting.test.d.ts
packages/lib/models/Setting.test.js
packages/lib/models/Setting.test.js.map
packages/lib/models/SmartFilter.d.ts
packages/lib/models/SmartFilter.js
packages/lib/models/SmartFilter.js.map
packages/lib/models/Tag.d.ts
packages/lib/models/Tag.js
packages/lib/models/Tag.js.map
packages/lib/models/dateTimeFormats.test.d.ts
packages/lib/models/dateTimeFormats.test.js
packages/lib/models/dateTimeFormats.test.js.map
packages/lib/models/settings/FileHandler.d.ts
packages/lib/models/settings/FileHandler.js
packages/lib/models/settings/FileHandler.js.map
@@ -1046,6 +989,9 @@ packages/lib/reducer.js.map
packages/lib/registry.d.ts
packages/lib/registry.js
packages/lib/registry.js.map
packages/lib/registry.test.d.ts
packages/lib/registry.test.js
packages/lib/registry.test.js.map
packages/lib/services/AlarmService.d.ts
packages/lib/services/AlarmService.js
packages/lib/services/AlarmService.js.map
@@ -1058,6 +1004,9 @@ packages/lib/services/BaseService.js.map
packages/lib/services/CommandService.d.ts
packages/lib/services/CommandService.js
packages/lib/services/CommandService.js.map
packages/lib/services/CommandService.test.d.ts
packages/lib/services/CommandService.test.js
packages/lib/services/CommandService.test.js.map
packages/lib/services/DecryptionWorker.d.ts
packages/lib/services/DecryptionWorker.js
packages/lib/services/DecryptionWorker.js.map
@@ -1106,6 +1055,9 @@ packages/lib/services/ResourceFetcher.js.map
packages/lib/services/ResourceService.d.ts
packages/lib/services/ResourceService.js
packages/lib/services/ResourceService.js.map
packages/lib/services/ResourceService.test.d.ts
packages/lib/services/ResourceService.test.js
packages/lib/services/ResourceService.test.js.map
packages/lib/services/RevisionService.d.ts
packages/lib/services/RevisionService.js
packages/lib/services/RevisionService.js.map
@@ -1154,6 +1106,9 @@ packages/lib/services/debug/populateDatabase.js.map
packages/lib/services/interop/InteropService.d.ts
packages/lib/services/interop/InteropService.js
packages/lib/services/interop/InteropService.js.map
packages/lib/services/interop/InteropService.test.d.ts
packages/lib/services/interop/InteropService.test.js
packages/lib/services/interop/InteropService.test.js.map
packages/lib/services/interop/InteropService_Exporter_Base.d.ts
packages/lib/services/interop/InteropService_Exporter_Base.js
packages/lib/services/interop/InteropService_Exporter_Base.js.map
@@ -1163,6 +1118,9 @@ packages/lib/services/interop/InteropService_Exporter_Custom.js.map
packages/lib/services/interop/InteropService_Exporter_Html.d.ts
packages/lib/services/interop/InteropService_Exporter_Html.js
packages/lib/services/interop/InteropService_Exporter_Html.js.map
packages/lib/services/interop/InteropService_Exporter_Html.test.d.ts
packages/lib/services/interop/InteropService_Exporter_Html.test.js
packages/lib/services/interop/InteropService_Exporter_Html.test.js.map
packages/lib/services/interop/InteropService_Exporter_Jex.d.ts
packages/lib/services/interop/InteropService_Exporter_Jex.js
packages/lib/services/interop/InteropService_Exporter_Jex.js.map
@@ -1325,6 +1283,9 @@ packages/lib/services/plugins/utils/validatePluginId.test.js.map
packages/lib/services/rest/Api.d.ts
packages/lib/services/rest/Api.js
packages/lib/services/rest/Api.js.map
packages/lib/services/rest/Api.test.d.ts
packages/lib/services/rest/Api.test.js
packages/lib/services/rest/Api.test.js.map
packages/lib/services/rest/ApiResponse.d.ts
packages/lib/services/rest/ApiResponse.js
packages/lib/services/rest/ApiResponse.js.map
@@ -1385,6 +1346,9 @@ packages/lib/services/searchengine/SearchEngine.js.map
packages/lib/services/searchengine/SearchEngineUtils.d.ts
packages/lib/services/searchengine/SearchEngineUtils.js
packages/lib/services/searchengine/SearchEngineUtils.js.map
packages/lib/services/searchengine/SearchEngineUtils.test.d.ts
packages/lib/services/searchengine/SearchEngineUtils.test.js
packages/lib/services/searchengine/SearchEngineUtils.test.js.map
packages/lib/services/searchengine/filterParser.d.ts
packages/lib/services/searchengine/filterParser.js
packages/lib/services/searchengine/filterParser.js.map
@@ -1409,6 +1373,30 @@ packages/lib/services/synchronizer/LockHandler.js.map
packages/lib/services/synchronizer/MigrationHandler.d.ts
packages/lib/services/synchronizer/MigrationHandler.js
packages/lib/services/synchronizer/MigrationHandler.js.map
packages/lib/services/synchronizer/Synchronizer.basics.test.d.ts
packages/lib/services/synchronizer/Synchronizer.basics.test.js
packages/lib/services/synchronizer/Synchronizer.basics.test.js.map
packages/lib/services/synchronizer/Synchronizer.conflicts.test.d.ts
packages/lib/services/synchronizer/Synchronizer.conflicts.test.js
packages/lib/services/synchronizer/Synchronizer.conflicts.test.js.map
packages/lib/services/synchronizer/Synchronizer.e2ee.test.d.ts
packages/lib/services/synchronizer/Synchronizer.e2ee.test.js
packages/lib/services/synchronizer/Synchronizer.e2ee.test.js.map
packages/lib/services/synchronizer/Synchronizer.resources.test.d.ts
packages/lib/services/synchronizer/Synchronizer.resources.test.js
packages/lib/services/synchronizer/Synchronizer.resources.test.js.map
packages/lib/services/synchronizer/Synchronizer.revisions.test.d.ts
packages/lib/services/synchronizer/Synchronizer.revisions.test.js
packages/lib/services/synchronizer/Synchronizer.revisions.test.js.map
packages/lib/services/synchronizer/Synchronizer.sharing.test.d.ts
packages/lib/services/synchronizer/Synchronizer.sharing.test.js
packages/lib/services/synchronizer/Synchronizer.sharing.test.js.map
packages/lib/services/synchronizer/Synchronizer.tags.test.d.ts
packages/lib/services/synchronizer/Synchronizer.tags.test.js
packages/lib/services/synchronizer/Synchronizer.tags.test.js.map
packages/lib/services/synchronizer/Synchronizer.tools.test.d.ts
packages/lib/services/synchronizer/Synchronizer.tools.test.js
packages/lib/services/synchronizer/Synchronizer.tools.test.js.map
packages/lib/services/synchronizer/gui/useSyncTargetUpgrade.d.ts
packages/lib/services/synchronizer/gui/useSyncTargetUpgrade.js
packages/lib/services/synchronizer/gui/useSyncTargetUpgrade.js.map
@@ -1418,6 +1406,12 @@ packages/lib/services/synchronizer/migrations/1.js.map
packages/lib/services/synchronizer/migrations/2.d.ts
packages/lib/services/synchronizer/migrations/2.js
packages/lib/services/synchronizer/migrations/2.js.map
packages/lib/services/synchronizer/synchronizer_LockHandler.test.d.ts
packages/lib/services/synchronizer/synchronizer_LockHandler.test.js
packages/lib/services/synchronizer/synchronizer_LockHandler.test.js.map
packages/lib/services/synchronizer/synchronizer_MigrationHandler.test.d.ts
packages/lib/services/synchronizer/synchronizer_MigrationHandler.test.js
packages/lib/services/synchronizer/synchronizer_MigrationHandler.test.js.map
packages/lib/services/synchronizer/tools.d.ts
packages/lib/services/synchronizer/tools.js
packages/lib/services/synchronizer/tools.js.map
@@ -1430,6 +1424,12 @@ packages/lib/services/synchronizer/utils/types.js.map
packages/lib/shim.d.ts
packages/lib/shim.js
packages/lib/shim.js.map
packages/lib/testing/test-utils-synchronizer.d.ts
packages/lib/testing/test-utils-synchronizer.js
packages/lib/testing/test-utils-synchronizer.js.map
packages/lib/testing/test-utils.d.ts
packages/lib/testing/test-utils.js
packages/lib/testing/test-utils.js.map
packages/lib/theme.d.ts
packages/lib/theme.js
packages/lib/theme.js.map
@@ -1463,6 +1463,9 @@ packages/lib/themes/type.js.map
packages/lib/time.d.ts
packages/lib/time.js
packages/lib/time.js.map
packages/lib/utils/credentialFiles.d.ts
packages/lib/utils/credentialFiles.js
packages/lib/utils/credentialFiles.js.map
packages/lib/uuid.d.ts
packages/lib/uuid.js
packages/lib/uuid.js.map

195
.gitignore vendored
View File

@@ -60,75 +60,21 @@ packages/app-cli/app/command-settingschema.js.map
packages/app-cli/app/services/plugins/PluginRunner.d.ts
packages/app-cli/app/services/plugins/PluginRunner.js
packages/app-cli/app/services/plugins/PluginRunner.js.map
packages/app-cli/tests/EnexToMd.d.ts
packages/app-cli/tests/EnexToMd.js
packages/app-cli/tests/EnexToMd.js.map
packages/app-cli/tests/HtmlToMd.d.ts
packages/app-cli/tests/HtmlToMd.js
packages/app-cli/tests/HtmlToMd.js.map
packages/app-cli/tests/InMemoryCache.d.ts
packages/app-cli/tests/InMemoryCache.js
packages/app-cli/tests/InMemoryCache.js.map
packages/app-cli/tests/MdToHtml.d.ts
packages/app-cli/tests/MdToHtml.js
packages/app-cli/tests/MdToHtml.js.map
packages/app-cli/tests/MdToMd.d.ts
packages/app-cli/tests/MdToMd.js
packages/app-cli/tests/MdToMd.js.map
packages/app-cli/tests/Synchronizer.basics.d.ts
packages/app-cli/tests/Synchronizer.basics.js
packages/app-cli/tests/Synchronizer.basics.js.map
packages/app-cli/tests/Synchronizer.conflicts.d.ts
packages/app-cli/tests/Synchronizer.conflicts.js
packages/app-cli/tests/Synchronizer.conflicts.js.map
packages/app-cli/tests/Synchronizer.e2ee.d.ts
packages/app-cli/tests/Synchronizer.e2ee.js
packages/app-cli/tests/Synchronizer.e2ee.js.map
packages/app-cli/tests/Synchronizer.resources.d.ts
packages/app-cli/tests/Synchronizer.resources.js
packages/app-cli/tests/Synchronizer.resources.js.map
packages/app-cli/tests/Synchronizer.revisions.d.ts
packages/app-cli/tests/Synchronizer.revisions.js
packages/app-cli/tests/Synchronizer.revisions.js.map
packages/app-cli/tests/Synchronizer.sharing.d.ts
packages/app-cli/tests/Synchronizer.sharing.js
packages/app-cli/tests/Synchronizer.sharing.js.map
packages/app-cli/tests/Synchronizer.tags.d.ts
packages/app-cli/tests/Synchronizer.tags.js
packages/app-cli/tests/Synchronizer.tags.js.map
packages/app-cli/tests/Synchronizer.tools.d.ts
packages/app-cli/tests/Synchronizer.tools.js
packages/app-cli/tests/Synchronizer.tools.js.map
packages/app-cli/tests/dateTimeFormats.d.ts
packages/app-cli/tests/dateTimeFormats.js
packages/app-cli/tests/dateTimeFormats.js.map
packages/app-cli/tests/file-api-driver.d.ts
packages/app-cli/tests/file-api-driver.js
packages/app-cli/tests/file-api-driver.js.map
packages/app-cli/tests/fsDriver.d.ts
packages/app-cli/tests/fsDriver.js
packages/app-cli/tests/fsDriver.js.map
packages/app-cli/tests/htmlUtils.d.ts
packages/app-cli/tests/htmlUtils.js
packages/app-cli/tests/htmlUtils.js.map
packages/app-cli/tests/markdownUtils.d.ts
packages/app-cli/tests/markdownUtils.js
packages/app-cli/tests/markdownUtils.js.map
packages/app-cli/tests/models_Folder.d.ts
packages/app-cli/tests/models_Folder.js
packages/app-cli/tests/models_Folder.js.map
packages/app-cli/tests/models_Folder.sharing.d.ts
packages/app-cli/tests/models_Folder.sharing.js
packages/app-cli/tests/models_Folder.sharing.js.map
packages/app-cli/tests/models_Note.d.ts
packages/app-cli/tests/models_Note.js
packages/app-cli/tests/models_Note.js.map
packages/app-cli/tests/models_Setting.d.ts
packages/app-cli/tests/models_Setting.js
packages/app-cli/tests/models_Setting.js.map
packages/app-cli/tests/registry.d.ts
packages/app-cli/tests/registry.js
packages/app-cli/tests/registry.js.map
packages/app-cli/tests/services/keychain/KeychainService.d.ts
packages/app-cli/tests/services/keychain/KeychainService.js
packages/app-cli/tests/services/keychain/KeychainService.js.map
packages/app-cli/tests/services/plugins/PluginService.d.ts
packages/app-cli/tests/services/plugins/PluginService.js
packages/app-cli/tests/services/plugins/PluginService.js.map
packages/app-cli/tests/services/plugins/RepositoryApi.d.ts
packages/app-cli/tests/services/plugins/RepositoryApi.js
packages/app-cli/tests/services/plugins/RepositoryApi.js.map
@@ -144,42 +90,6 @@ packages/app-cli/tests/services/plugins/api/JoplinWorkspace.js.map
packages/app-cli/tests/services/plugins/sandboxProxy.d.ts
packages/app-cli/tests/services/plugins/sandboxProxy.js
packages/app-cli/tests/services/plugins/sandboxProxy.js.map
packages/app-cli/tests/services_CommandService.d.ts
packages/app-cli/tests/services_CommandService.js
packages/app-cli/tests/services_CommandService.js.map
packages/app-cli/tests/services_InteropService.d.ts
packages/app-cli/tests/services_InteropService.js
packages/app-cli/tests/services_InteropService.js.map
packages/app-cli/tests/services_InteropService_Exporter_Html.d.ts
packages/app-cli/tests/services_InteropService_Exporter_Html.js
packages/app-cli/tests/services_InteropService_Exporter_Html.js.map
packages/app-cli/tests/services_PluginService.d.ts
packages/app-cli/tests/services_PluginService.js
packages/app-cli/tests/services_PluginService.js.map
packages/app-cli/tests/services_ResourceService.d.ts
packages/app-cli/tests/services_ResourceService.js
packages/app-cli/tests/services_ResourceService.js.map
packages/app-cli/tests/services_SearchEngineUtils.d.ts
packages/app-cli/tests/services_SearchEngineUtils.js
packages/app-cli/tests/services_SearchEngineUtils.js.map
packages/app-cli/tests/services_keychainService.d.ts
packages/app-cli/tests/services_keychainService.js
packages/app-cli/tests/services_keychainService.js.map
packages/app-cli/tests/services_rest_Api.d.ts
packages/app-cli/tests/services_rest_Api.js
packages/app-cli/tests/services_rest_Api.js.map
packages/app-cli/tests/synchronizer_LockHandler.d.ts
packages/app-cli/tests/synchronizer_LockHandler.js
packages/app-cli/tests/synchronizer_LockHandler.js.map
packages/app-cli/tests/synchronizer_MigrationHandler.d.ts
packages/app-cli/tests/synchronizer_MigrationHandler.js
packages/app-cli/tests/synchronizer_MigrationHandler.js.map
packages/app-cli/tests/test-utils-synchronizer.d.ts
packages/app-cli/tests/test-utils-synchronizer.js
packages/app-cli/tests/test-utils-synchronizer.js.map
packages/app-cli/tests/test-utils.d.ts
packages/app-cli/tests/test-utils.js
packages/app-cli/tests/test-utils.js.map
packages/app-desktop/ElectronAppWrapper.d.ts
packages/app-desktop/ElectronAppWrapper.js
packages/app-desktop/ElectronAppWrapper.js.map
@@ -876,6 +786,9 @@ packages/lib/HtmlToMd.js.map
packages/lib/InMemoryCache.d.ts
packages/lib/InMemoryCache.js
packages/lib/InMemoryCache.js.map
packages/lib/InMemoryCache.test.d.ts
packages/lib/InMemoryCache.test.js
packages/lib/InMemoryCache.test.js.map
packages/lib/JoplinDatabase.d.ts
packages/lib/JoplinDatabase.js
packages/lib/JoplinDatabase.js.map
@@ -927,6 +840,9 @@ packages/lib/eventManager.js.map
packages/lib/file-api-driver-joplinServer.d.ts
packages/lib/file-api-driver-joplinServer.js
packages/lib/file-api-driver-joplinServer.js.map
packages/lib/file-api-driver.test.d.ts
packages/lib/file-api-driver.test.js
packages/lib/file-api-driver.test.js.map
packages/lib/file-api.d.ts
packages/lib/file-api.js
packages/lib/file-api.js.map
@@ -936,15 +852,24 @@ packages/lib/fs-driver-base.js.map
packages/lib/fs-driver-node.d.ts
packages/lib/fs-driver-node.js
packages/lib/fs-driver-node.js.map
packages/lib/fsDriver.test.d.ts
packages/lib/fsDriver.test.js
packages/lib/fsDriver.test.js.map
packages/lib/htmlUtils.d.ts
packages/lib/htmlUtils.js
packages/lib/htmlUtils.js.map
packages/lib/htmlUtils.test.d.ts
packages/lib/htmlUtils.test.js
packages/lib/htmlUtils.test.js.map
packages/lib/htmlUtils2.test.d.ts
packages/lib/htmlUtils2.test.js
packages/lib/htmlUtils2.test.js.map
packages/lib/import-enex-md-gen.d.ts
packages/lib/import-enex-md-gen.js
packages/lib/import-enex-md-gen.js.map
packages/lib/import-enex-md-gen.test.d.ts
packages/lib/import-enex-md-gen.test.js
packages/lib/import-enex-md-gen.test.js.map
packages/lib/locale.d.ts
packages/lib/locale.js
packages/lib/locale.js.map
@@ -954,6 +879,9 @@ packages/lib/markdownUtils.js.map
packages/lib/markdownUtils.test.d.ts
packages/lib/markdownUtils.test.js
packages/lib/markdownUtils.test.js.map
packages/lib/markdownUtils2.test.d.ts
packages/lib/markdownUtils2.test.js
packages/lib/markdownUtils2.test.js.map
packages/lib/markupLanguageUtils.d.ts
packages/lib/markupLanguageUtils.js
packages/lib/markupLanguageUtils.js.map
@@ -966,6 +894,12 @@ packages/lib/models/BaseItem.js.map
packages/lib/models/Folder.d.ts
packages/lib/models/Folder.js
packages/lib/models/Folder.js.map
packages/lib/models/Folder.sharing.test.d.ts
packages/lib/models/Folder.sharing.test.js
packages/lib/models/Folder.sharing.test.js.map
packages/lib/models/Folder.test.d.ts
packages/lib/models/Folder.test.js
packages/lib/models/Folder.test.js.map
packages/lib/models/ItemChange.d.ts
packages/lib/models/ItemChange.js
packages/lib/models/ItemChange.js.map
@@ -978,6 +912,9 @@ packages/lib/models/Migration.js.map
packages/lib/models/Note.d.ts
packages/lib/models/Note.js
packages/lib/models/Note.js.map
packages/lib/models/Note.test.d.ts
packages/lib/models/Note.test.js
packages/lib/models/Note.test.js.map
packages/lib/models/NoteResource.d.ts
packages/lib/models/NoteResource.js
packages/lib/models/NoteResource.js.map
@@ -999,12 +936,18 @@ packages/lib/models/Search.js.map
packages/lib/models/Setting.d.ts
packages/lib/models/Setting.js
packages/lib/models/Setting.js.map
packages/lib/models/Setting.test.d.ts
packages/lib/models/Setting.test.js
packages/lib/models/Setting.test.js.map
packages/lib/models/SmartFilter.d.ts
packages/lib/models/SmartFilter.js
packages/lib/models/SmartFilter.js.map
packages/lib/models/Tag.d.ts
packages/lib/models/Tag.js
packages/lib/models/Tag.js.map
packages/lib/models/dateTimeFormats.test.d.ts
packages/lib/models/dateTimeFormats.test.js
packages/lib/models/dateTimeFormats.test.js.map
packages/lib/models/settings/FileHandler.d.ts
packages/lib/models/settings/FileHandler.js
packages/lib/models/settings/FileHandler.js.map
@@ -1032,6 +975,9 @@ packages/lib/reducer.js.map
packages/lib/registry.d.ts
packages/lib/registry.js
packages/lib/registry.js.map
packages/lib/registry.test.d.ts
packages/lib/registry.test.js
packages/lib/registry.test.js.map
packages/lib/services/AlarmService.d.ts
packages/lib/services/AlarmService.js
packages/lib/services/AlarmService.js.map
@@ -1044,6 +990,9 @@ packages/lib/services/BaseService.js.map
packages/lib/services/CommandService.d.ts
packages/lib/services/CommandService.js
packages/lib/services/CommandService.js.map
packages/lib/services/CommandService.test.d.ts
packages/lib/services/CommandService.test.js
packages/lib/services/CommandService.test.js.map
packages/lib/services/DecryptionWorker.d.ts
packages/lib/services/DecryptionWorker.js
packages/lib/services/DecryptionWorker.js.map
@@ -1092,6 +1041,9 @@ packages/lib/services/ResourceFetcher.js.map
packages/lib/services/ResourceService.d.ts
packages/lib/services/ResourceService.js
packages/lib/services/ResourceService.js.map
packages/lib/services/ResourceService.test.d.ts
packages/lib/services/ResourceService.test.js
packages/lib/services/ResourceService.test.js.map
packages/lib/services/RevisionService.d.ts
packages/lib/services/RevisionService.js
packages/lib/services/RevisionService.js.map
@@ -1140,6 +1092,9 @@ packages/lib/services/debug/populateDatabase.js.map
packages/lib/services/interop/InteropService.d.ts
packages/lib/services/interop/InteropService.js
packages/lib/services/interop/InteropService.js.map
packages/lib/services/interop/InteropService.test.d.ts
packages/lib/services/interop/InteropService.test.js
packages/lib/services/interop/InteropService.test.js.map
packages/lib/services/interop/InteropService_Exporter_Base.d.ts
packages/lib/services/interop/InteropService_Exporter_Base.js
packages/lib/services/interop/InteropService_Exporter_Base.js.map
@@ -1149,6 +1104,9 @@ packages/lib/services/interop/InteropService_Exporter_Custom.js.map
packages/lib/services/interop/InteropService_Exporter_Html.d.ts
packages/lib/services/interop/InteropService_Exporter_Html.js
packages/lib/services/interop/InteropService_Exporter_Html.js.map
packages/lib/services/interop/InteropService_Exporter_Html.test.d.ts
packages/lib/services/interop/InteropService_Exporter_Html.test.js
packages/lib/services/interop/InteropService_Exporter_Html.test.js.map
packages/lib/services/interop/InteropService_Exporter_Jex.d.ts
packages/lib/services/interop/InteropService_Exporter_Jex.js
packages/lib/services/interop/InteropService_Exporter_Jex.js.map
@@ -1311,6 +1269,9 @@ packages/lib/services/plugins/utils/validatePluginId.test.js.map
packages/lib/services/rest/Api.d.ts
packages/lib/services/rest/Api.js
packages/lib/services/rest/Api.js.map
packages/lib/services/rest/Api.test.d.ts
packages/lib/services/rest/Api.test.js
packages/lib/services/rest/Api.test.js.map
packages/lib/services/rest/ApiResponse.d.ts
packages/lib/services/rest/ApiResponse.js
packages/lib/services/rest/ApiResponse.js.map
@@ -1371,6 +1332,9 @@ packages/lib/services/searchengine/SearchEngine.js.map
packages/lib/services/searchengine/SearchEngineUtils.d.ts
packages/lib/services/searchengine/SearchEngineUtils.js
packages/lib/services/searchengine/SearchEngineUtils.js.map
packages/lib/services/searchengine/SearchEngineUtils.test.d.ts
packages/lib/services/searchengine/SearchEngineUtils.test.js
packages/lib/services/searchengine/SearchEngineUtils.test.js.map
packages/lib/services/searchengine/filterParser.d.ts
packages/lib/services/searchengine/filterParser.js
packages/lib/services/searchengine/filterParser.js.map
@@ -1395,6 +1359,30 @@ packages/lib/services/synchronizer/LockHandler.js.map
packages/lib/services/synchronizer/MigrationHandler.d.ts
packages/lib/services/synchronizer/MigrationHandler.js
packages/lib/services/synchronizer/MigrationHandler.js.map
packages/lib/services/synchronizer/Synchronizer.basics.test.d.ts
packages/lib/services/synchronizer/Synchronizer.basics.test.js
packages/lib/services/synchronizer/Synchronizer.basics.test.js.map
packages/lib/services/synchronizer/Synchronizer.conflicts.test.d.ts
packages/lib/services/synchronizer/Synchronizer.conflicts.test.js
packages/lib/services/synchronizer/Synchronizer.conflicts.test.js.map
packages/lib/services/synchronizer/Synchronizer.e2ee.test.d.ts
packages/lib/services/synchronizer/Synchronizer.e2ee.test.js
packages/lib/services/synchronizer/Synchronizer.e2ee.test.js.map
packages/lib/services/synchronizer/Synchronizer.resources.test.d.ts
packages/lib/services/synchronizer/Synchronizer.resources.test.js
packages/lib/services/synchronizer/Synchronizer.resources.test.js.map
packages/lib/services/synchronizer/Synchronizer.revisions.test.d.ts
packages/lib/services/synchronizer/Synchronizer.revisions.test.js
packages/lib/services/synchronizer/Synchronizer.revisions.test.js.map
packages/lib/services/synchronizer/Synchronizer.sharing.test.d.ts
packages/lib/services/synchronizer/Synchronizer.sharing.test.js
packages/lib/services/synchronizer/Synchronizer.sharing.test.js.map
packages/lib/services/synchronizer/Synchronizer.tags.test.d.ts
packages/lib/services/synchronizer/Synchronizer.tags.test.js
packages/lib/services/synchronizer/Synchronizer.tags.test.js.map
packages/lib/services/synchronizer/Synchronizer.tools.test.d.ts
packages/lib/services/synchronizer/Synchronizer.tools.test.js
packages/lib/services/synchronizer/Synchronizer.tools.test.js.map
packages/lib/services/synchronizer/gui/useSyncTargetUpgrade.d.ts
packages/lib/services/synchronizer/gui/useSyncTargetUpgrade.js
packages/lib/services/synchronizer/gui/useSyncTargetUpgrade.js.map
@@ -1404,6 +1392,12 @@ packages/lib/services/synchronizer/migrations/1.js.map
packages/lib/services/synchronizer/migrations/2.d.ts
packages/lib/services/synchronizer/migrations/2.js
packages/lib/services/synchronizer/migrations/2.js.map
packages/lib/services/synchronizer/synchronizer_LockHandler.test.d.ts
packages/lib/services/synchronizer/synchronizer_LockHandler.test.js
packages/lib/services/synchronizer/synchronizer_LockHandler.test.js.map
packages/lib/services/synchronizer/synchronizer_MigrationHandler.test.d.ts
packages/lib/services/synchronizer/synchronizer_MigrationHandler.test.js
packages/lib/services/synchronizer/synchronizer_MigrationHandler.test.js.map
packages/lib/services/synchronizer/tools.d.ts
packages/lib/services/synchronizer/tools.js
packages/lib/services/synchronizer/tools.js.map
@@ -1416,6 +1410,12 @@ packages/lib/services/synchronizer/utils/types.js.map
packages/lib/shim.d.ts
packages/lib/shim.js
packages/lib/shim.js.map
packages/lib/testing/test-utils-synchronizer.d.ts
packages/lib/testing/test-utils-synchronizer.js
packages/lib/testing/test-utils-synchronizer.js.map
packages/lib/testing/test-utils.d.ts
packages/lib/testing/test-utils.js
packages/lib/testing/test-utils.js.map
packages/lib/theme.d.ts
packages/lib/theme.js
packages/lib/theme.js.map
@@ -1449,6 +1449,9 @@ packages/lib/themes/type.js.map
packages/lib/time.d.ts
packages/lib/time.js
packages/lib/time.js.map
packages/lib/utils/credentialFiles.d.ts
packages/lib/utils/credentialFiles.js
packages/lib/utils/credentialFiles.js.map
packages/lib/uuid.d.ts
packages/lib/uuid.js
packages/lib/uuid.js.map

View File

@@ -1,4 +1,17 @@
const { afterEachCleanUp } = require('./tests/test-utils.js');
const { afterEachCleanUp } = require('@joplin/lib/testing/test-utils.js');
const { shimInit } = require('@joplin/lib/shim-init-node.js');
const shim = require('@joplin/lib/shim').default;
const sharp = require('sharp');
let keytar;
try {
keytar = shim.platformSupportsKeyChain() ? require('keytar') : null;
} catch (error) {
console.error('Cannot load keytar - keychain support will be disabled', error);
keytar = null;
}
shimInit(sharp, keytar);
global.afterEach(async () => {
await afterEachCleanUp();

View File

@@ -43,7 +43,6 @@
"@joplin/renderer": "1.8",
"aws-sdk": "^2.588.0",
"chalk": "^4.1.0",
"clean-html": "^1.5.0",
"compare-version": "^0.1.2",
"fs-extra": "^5.0.0",
"html-entities": "^1.2.1",

View File

@@ -1,116 +0,0 @@
const { setupDatabaseAndSynchronizer, switchClient } = require('./test-utils.js');
const shim = require('@joplin/lib/shim').default;
const { enexXmlToHtml } = require('@joplin/lib/import-enex-html-gen.js');
const cleanHtml = require('clean-html');
const fileWithPath = (filename) =>
`${__dirname}/enex_to_html/${filename}`;
const audioResource = {
filename: 'audio test',
id: '9168ee833d03c5ea7c730ac6673978c1',
mime: 'audio/x-m4a',
size: 82011,
title: 'audio test',
};
// All the test HTML files are beautified ones, so we need to run
// this before the comparison. Before, beautifying was done by `enexXmlToHtml`
// but that was removed due to problems with the clean-html package.
const beautifyHtml = (html) => {
return new Promise((resolve) => {
try {
cleanHtml.clean(html, { wrap: 0 }, (...cleanedHtml) => resolve(cleanedHtml.join('')));
} catch (error) {
console.warn(`Could not clean HTML - the "unclean" version will be used: ${error.message}: ${html.trim().substr(0, 512).replace(/[\n\r]/g, ' ')}...`);
resolve([html].join(''));
}
});
};
/**
* Tests the importer for a single note, checking that the result of
* processing the given `.enex` input file matches the contents of the given
* `.html` file.
*
* Note that this does not test the importing of an entire exported `.enex`
* archive, but rather a single node of such a file. Thus, the test data files
* (e.g. `./enex_to_html/code1.enex`) correspond to the contents of a single
* `<note>...</note>` node in an `.enex` file already extracted from
* `<content><![CDATA[...]]</content>`.
*/
const compareOutputToExpected = (options) => {
const inputFile = fileWithPath(`${options.testName}.enex`);
const outputFile = fileWithPath(`${options.testName}.html`);
const testTitle = `should convert from Enex to Html: ${options.testName}`;
it(testTitle, (async () => {
const enexInput = await shim.fsDriver().readFile(inputFile);
const expectedOutput = await shim.fsDriver().readFile(outputFile);
const actualOutput = await beautifyHtml(await enexXmlToHtml(enexInput, options.resources));
expect(actualOutput).toEqual(expectedOutput);
}));
};
describe('EnexToHtml', function() {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
});
compareOutputToExpected({
testName: 'checklist-list',
resources: [],
});
compareOutputToExpected({
testName: 'svg',
resources: [],
});
compareOutputToExpected({
testName: 'en-media--image',
resources: [{
filename: '',
id: '89ce7da62c6b2832929a6964237e98e9', // Mock id
mime: 'image/jpeg',
size: 50347,
title: '',
}],
});
compareOutputToExpected({
testName: 'en-media--audio',
resources: [audioResource],
});
compareOutputToExpected({
testName: 'attachment',
resources: [{
filename: 'attachment-1',
id: '21ca2b948f222a38802940ec7e2e5de3',
mime: 'application/pdf', // Any non-image/non-audio mime type will do
size: 1000,
}],
});
// it('fails when not given a matching resource', (async () => {
// // To test the promise-unexpectedly-resolved case, add `audioResource` to the array.
// const resources = [];
// const inputFile = fileWithPath('en-media--image.enex');
// const enexInput = await shim.fsDriver().readFile(inputFile);
// const promisedOutput = enexXmlToHtml(enexInput, resources);
// promisedOutput.then(() => {
// // Promise should not be resolved
// expect(false).toEqual(true);
// }, (reason) => {
// expect(reason)
// .toBe('Hash with no associated resource: 89ce7da62c6b2832929a6964237e98e9');
// });
// }));
});

View File

@@ -4,7 +4,7 @@
const os = require('os');
const time = require('@joplin/lib/time').default;
const { filename } = require('@joplin/lib/path-utils');
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('@joplin/lib/testing/test-utils.js');
const Folder = require('@joplin/lib/models/Folder').default;
const Note = require('@joplin/lib/models/Note').default;
const BaseModel = require('@joplin/lib/BaseModel').default;

View File

@@ -1,7 +1,7 @@
import MdToHtml from '@joplin/renderer/MdToHtml';
const os = require('os');
const { filename } = require('@joplin/lib/path-utils');
const { setupDatabaseAndSynchronizer, switchClient } = require('./test-utils.js');
const { setupDatabaseAndSynchronizer, switchClient } = require('@joplin/lib/testing/test-utils.js');
import shim from '@joplin/lib/shim';
const { themeStyle } = require('@joplin/lib/theme');

View File

@@ -1,6 +1,6 @@
const mdImporterService = require('@joplin/lib/services/interop/InteropService_Importer_Md').default;
const Note = require('@joplin/lib/models/Note').default;
const { setupDatabaseAndSynchronizer, switchClient } = require('./test-utils.js');
const { setupDatabaseAndSynchronizer, switchClient } = require('@joplin/lib/testing/test-utils.js');
const importer = new mdImporterService();

View File

@@ -1,290 +0,0 @@
'use strict';
const __awaiter = (this && this.__awaiter) || function(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function(resolve) { resolve(value); }); }
return new (P || (P = Promise))(function(resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator['throw'](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, '__esModule', { value: true });
const Setting_1 = require('@joplin/lib/models/Setting');
const test_utils_synchronizer_1 = require('./test-utils-synchronizer');
const { syncTargetName, afterAllCleanUp, synchronizerStart, setupDatabaseAndSynchronizer, synchronizer, sleep, switchClient, syncTargetId, fileApi } = require('./test-utils.js');
const Folder_1 = require('@joplin/lib/models/Folder');
const Note_1 = require('@joplin/lib/models/Note');
const BaseItem_1 = require('@joplin/lib/models/BaseItem');
const WelcomeUtils = require('@joplin/lib/WelcomeUtils');
describe('Synchronizer.basics', function() {
beforeEach((done) => __awaiter(this, void 0, void 0, function* () {
yield setupDatabaseAndSynchronizer(1);
yield setupDatabaseAndSynchronizer(2);
yield switchClient(1);
done();
}));
afterAll(() => __awaiter(this, void 0, void 0, function* () {
yield afterAllCleanUp();
}));
it('should create remote items', (() => __awaiter(this, void 0, void 0, function* () {
const folder = yield Folder_1.default.save({ title: 'folder1' });
yield Note_1.default.save({ title: 'un', parent_id: folder.id });
const all = yield test_utils_synchronizer_1.allNotesFolders();
yield synchronizerStart();
yield test_utils_synchronizer_1.localNotesFoldersSameAsRemote(all, expect);
})));
it('should update remote items', (() => __awaiter(this, void 0, void 0, function* () {
const folder = yield Folder_1.default.save({ title: 'folder1' });
const note = yield Note_1.default.save({ title: 'un', parent_id: folder.id });
yield synchronizerStart();
yield Note_1.default.save({ title: 'un UPDATE', id: note.id });
const all = yield test_utils_synchronizer_1.allNotesFolders();
yield synchronizerStart();
yield test_utils_synchronizer_1.localNotesFoldersSameAsRemote(all, expect);
})));
it('should create local items', (() => __awaiter(this, void 0, void 0, function* () {
const folder = yield Folder_1.default.save({ title: 'folder1' });
yield Note_1.default.save({ title: 'un', parent_id: folder.id });
yield synchronizerStart();
yield switchClient(2);
yield synchronizerStart();
const all = yield test_utils_synchronizer_1.allNotesFolders();
yield test_utils_synchronizer_1.localNotesFoldersSameAsRemote(all, expect);
})));
it('should update local items', (() => __awaiter(this, void 0, void 0, function* () {
const folder1 = yield Folder_1.default.save({ title: 'folder1' });
const note1 = yield Note_1.default.save({ title: 'un', parent_id: folder1.id });
yield synchronizerStart();
yield switchClient(2);
yield synchronizerStart();
yield sleep(0.1);
let note2 = yield Note_1.default.load(note1.id);
note2.title = 'Updated on client 2';
yield Note_1.default.save(note2);
note2 = yield Note_1.default.load(note2.id);
yield synchronizerStart();
yield switchClient(1);
yield synchronizerStart();
const all = yield test_utils_synchronizer_1.allNotesFolders();
yield test_utils_synchronizer_1.localNotesFoldersSameAsRemote(all, expect);
})));
it('should delete remote notes', (() => __awaiter(this, void 0, void 0, function* () {
const folder1 = yield Folder_1.default.save({ title: 'folder1' });
const note1 = yield Note_1.default.save({ title: 'un', parent_id: folder1.id });
yield synchronizerStart();
yield switchClient(2);
yield synchronizerStart();
yield sleep(0.1);
yield Note_1.default.delete(note1.id);
yield synchronizerStart();
const remotes = yield test_utils_synchronizer_1.remoteNotesAndFolders();
expect(remotes.length).toBe(1);
expect(remotes[0].id).toBe(folder1.id);
const deletedItems = yield BaseItem_1.default.deletedItems(syncTargetId());
expect(deletedItems.length).toBe(0);
})));
it('should not created deleted_items entries for items deleted via sync', (() => __awaiter(this, void 0, void 0, function* () {
const folder1 = yield Folder_1.default.save({ title: 'folder1' });
yield Note_1.default.save({ title: 'un', parent_id: folder1.id });
yield synchronizerStart();
yield switchClient(2);
yield synchronizerStart();
yield Folder_1.default.delete(folder1.id);
yield synchronizerStart();
yield switchClient(1);
yield synchronizerStart();
const deletedItems = yield BaseItem_1.default.deletedItems(syncTargetId());
expect(deletedItems.length).toBe(0);
})));
it('should delete local notes', (() => __awaiter(this, void 0, void 0, function* () {
const folder1 = yield Folder_1.default.save({ title: 'folder1' });
const note1 = yield Note_1.default.save({ title: 'un', parent_id: folder1.id });
const note2 = yield Note_1.default.save({ title: 'deux', parent_id: folder1.id });
yield synchronizerStart();
yield switchClient(2);
yield synchronizerStart();
yield Note_1.default.delete(note1.id);
yield synchronizerStart();
yield switchClient(1);
yield synchronizerStart();
const items = yield test_utils_synchronizer_1.allNotesFolders();
expect(items.length).toBe(2);
const deletedItems = yield BaseItem_1.default.deletedItems(syncTargetId());
expect(deletedItems.length).toBe(0);
yield Note_1.default.delete(note2.id);
yield synchronizerStart();
})));
it('should delete remote folder', (() => __awaiter(this, void 0, void 0, function* () {
yield Folder_1.default.save({ title: 'folder1' });
const folder2 = yield Folder_1.default.save({ title: 'folder2' });
yield synchronizerStart();
yield switchClient(2);
yield synchronizerStart();
yield sleep(0.1);
yield Folder_1.default.delete(folder2.id);
yield synchronizerStart();
const all = yield test_utils_synchronizer_1.allNotesFolders();
yield test_utils_synchronizer_1.localNotesFoldersSameAsRemote(all, expect);
})));
it('should delete local folder', (() => __awaiter(this, void 0, void 0, function* () {
yield Folder_1.default.save({ title: 'folder1' });
const folder2 = yield Folder_1.default.save({ title: 'folder2' });
yield synchronizerStart();
yield switchClient(2);
yield synchronizerStart();
yield Folder_1.default.delete(folder2.id);
yield synchronizerStart();
yield switchClient(1);
yield synchronizerStart();
const items = yield test_utils_synchronizer_1.allNotesFolders();
yield test_utils_synchronizer_1.localNotesFoldersSameAsRemote(items, expect);
})));
it('should cross delete all folders', (() => __awaiter(this, void 0, void 0, function* () {
// If client1 and 2 have two folders, client 1 deletes item 1 and client
// 2 deletes item 2, they should both end up with no items after sync.
const folder1 = yield Folder_1.default.save({ title: 'folder1' });
const folder2 = yield Folder_1.default.save({ title: 'folder2' });
yield synchronizerStart();
yield switchClient(2);
yield synchronizerStart();
yield sleep(0.1);
yield Folder_1.default.delete(folder1.id);
yield switchClient(1);
yield Folder_1.default.delete(folder2.id);
yield synchronizerStart();
yield switchClient(2);
yield synchronizerStart();
const items2 = yield test_utils_synchronizer_1.allNotesFolders();
yield switchClient(1);
yield synchronizerStart();
const items1 = yield test_utils_synchronizer_1.allNotesFolders();
expect(items1.length).toBe(0);
expect(items1.length).toBe(items2.length);
})));
it('items should be downloaded again when user cancels in the middle of delta operation', (() => __awaiter(this, void 0, void 0, function* () {
const folder1 = yield Folder_1.default.save({ title: 'folder1' });
yield Note_1.default.save({ title: 'un', is_todo: 1, parent_id: folder1.id });
yield synchronizerStart();
yield switchClient(2);
synchronizer().testingHooks_ = ['cancelDeltaLoop2'];
yield synchronizerStart();
let notes = yield Note_1.default.all();
expect(notes.length).toBe(0);
synchronizer().testingHooks_ = [];
yield synchronizerStart();
notes = yield Note_1.default.all();
expect(notes.length).toBe(1);
})));
it('should skip items that cannot be synced', (() => __awaiter(this, void 0, void 0, function* () {
const folder1 = yield Folder_1.default.save({ title: 'folder1' });
const note1 = yield Note_1.default.save({ title: 'un', is_todo: 1, parent_id: folder1.id });
const noteId = note1.id;
yield synchronizerStart();
let disabledItems = yield BaseItem_1.default.syncDisabledItems(syncTargetId());
expect(disabledItems.length).toBe(0);
yield Note_1.default.save({ id: noteId, title: 'un mod' });
synchronizer().testingHooks_ = ['notesRejectedByTarget'];
yield synchronizerStart();
synchronizer().testingHooks_ = [];
yield synchronizerStart(); // Another sync to check that this item is now excluded from sync
yield switchClient(2);
yield synchronizerStart();
const notes = yield Note_1.default.all();
expect(notes.length).toBe(1);
expect(notes[0].title).toBe('un');
yield switchClient(1);
disabledItems = yield BaseItem_1.default.syncDisabledItems(syncTargetId());
expect(disabledItems.length).toBe(1);
})));
it('should allow duplicate folder titles', (() => __awaiter(this, void 0, void 0, function* () {
yield Folder_1.default.save({ title: 'folder' });
yield switchClient(2);
let remoteF2 = yield Folder_1.default.save({ title: 'folder' });
yield synchronizerStart();
yield switchClient(1);
yield sleep(0.1);
yield synchronizerStart();
const localF2 = yield Folder_1.default.load(remoteF2.id);
expect(localF2.title == remoteF2.title).toBe(true);
// Then that folder that has been renamed locally should be set in such a way
// that synchronizing it applies the title change remotely, and that new title
// should be retrieved by client 2.
yield synchronizerStart();
yield switchClient(2);
yield sleep(0.1);
yield synchronizerStart();
remoteF2 = yield Folder_1.default.load(remoteF2.id);
expect(remoteF2.title == localF2.title).toBe(true);
})));
it('should create remote items with UTF-8 content', (() => __awaiter(this, void 0, void 0, function* () {
const folder = yield Folder_1.default.save({ title: 'Fahrräder' });
yield Note_1.default.save({ title: 'Fahrräder', body: 'Fahrräder', parent_id: folder.id });
const all = yield test_utils_synchronizer_1.allNotesFolders();
yield synchronizerStart();
yield test_utils_synchronizer_1.localNotesFoldersSameAsRemote(all, expect);
})));
it('should update remote items but not pull remote changes', (() => __awaiter(this, void 0, void 0, function* () {
const folder = yield Folder_1.default.save({ title: 'folder1' });
const note = yield Note_1.default.save({ title: 'un', parent_id: folder.id });
yield synchronizerStart();
yield switchClient(2);
yield synchronizerStart();
yield Note_1.default.save({ title: 'deux', parent_id: folder.id });
yield synchronizerStart();
yield switchClient(1);
yield Note_1.default.save({ title: 'un UPDATE', id: note.id });
yield synchronizerStart(null, { syncSteps: ['update_remote'] });
const all = yield test_utils_synchronizer_1.allNotesFolders();
expect(all.length).toBe(2);
yield switchClient(2);
yield synchronizerStart();
const note2 = yield Note_1.default.load(note.id);
expect(note2.title).toBe('un UPDATE');
})));
it('should create a new Welcome notebook on each client', (() => __awaiter(this, void 0, void 0, function* () {
// Create the Welcome items on two separate clients
yield WelcomeUtils.createWelcomeItems();
yield synchronizerStart();
yield switchClient(2);
yield WelcomeUtils.createWelcomeItems();
const beforeFolderCount = (yield Folder_1.default.all()).length;
const beforeNoteCount = (yield Note_1.default.all()).length;
expect(beforeFolderCount === 1).toBe(true);
expect(beforeNoteCount > 1).toBe(true);
yield synchronizerStart();
const afterFolderCount = (yield Folder_1.default.all()).length;
const afterNoteCount = (yield Note_1.default.all()).length;
expect(afterFolderCount).toBe(beforeFolderCount * 2);
expect(afterNoteCount).toBe(beforeNoteCount * 2);
// Changes to the Welcome items should be synced to all clients
const f1 = (yield Folder_1.default.all())[0];
yield Folder_1.default.save({ id: f1.id, title: 'Welcome MOD' });
yield synchronizerStart();
yield switchClient(1);
yield synchronizerStart();
const f1_1 = yield Folder_1.default.load(f1.id);
expect(f1_1.title).toBe('Welcome MOD');
})));
it('should not wipe out user data when syncing with an empty target', (() => __awaiter(this, void 0, void 0, function* () {
// Only these targets support the wipeOutFailSafe flag (in other words, the targets that use basicDelta)
if (!['nextcloud', 'memory', 'filesystem', 'amazon_s3'].includes(syncTargetName())) { return; }
for (let i = 0; i < 10; i++) { yield Note_1.default.save({ title: 'note' }); }
Setting_1.default.setValue('sync.wipeOutFailSafe', true);
yield synchronizerStart();
yield fileApi().clearRoot(); // oops
yield synchronizerStart();
expect((yield Note_1.default.all()).length).toBe(10); // but since the fail-safe if on, the notes have not been deleted
Setting_1.default.setValue('sync.wipeOutFailSafe', false); // Now switch it off
yield synchronizerStart();
expect((yield Note_1.default.all()).length).toBe(0); // Since the fail-safe was off, the data has been cleared
// Handle case where the sync target has been wiped out, then the user creates one note and sync.
for (let i = 0; i < 10; i++) { yield Note_1.default.save({ title: 'note' }); }
Setting_1.default.setValue('sync.wipeOutFailSafe', true);
yield synchronizerStart();
yield fileApi().clearRoot();
yield Note_1.default.save({ title: 'ma note encore' });
yield synchronizerStart();
expect((yield Note_1.default.all()).length).toBe(11);
})));
});
// # sourceMappingURL=Synchronizer.share.js.map

View File

@@ -1,31 +0,0 @@
/* eslint-disable no-unused-vars */
const time = require('@joplin/lib/time').default;
const { sortedIds, createNTestNotes, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const Folder = require('@joplin/lib/models/Folder').default;
const Note = require('@joplin/lib/models/Note').default;
const Setting = require('@joplin/lib/models/Setting').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
const ArrayUtils = require('@joplin/lib/ArrayUtils.js');
const shim = require('@joplin/lib/shim').default;
describe('database', function() {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
});
it('should not modify cached field names', (async () => {
const db = BaseModel.db();
const fieldNames = db.tableFieldNames('notes');
const fieldCount = fieldNames.length;
fieldNames.push('type_');
expect(fieldCount).toBeGreaterThan(0);
expect(db.tableFieldNames('notes').length).toBe(fieldCount);
}));
});

View File

@@ -1,4 +1,4 @@
const { id, ids, createNTestFolders, sortedIds, createNTestNotes, TestApp } = require('./test-utils.js');
const { id, ids, createNTestFolders, sortedIds, createNTestNotes, TestApp } = require('@joplin/lib/testing/test-utils.js');
const BaseModel = require('@joplin/lib/BaseModel').default;
const uuid = require('@joplin/lib/uuid').default;
const Note = require('@joplin/lib/models/Note').default;

View File

@@ -1,5 +1,5 @@
/* eslint-disable no-unused-vars */
const { setupDatabaseAndSynchronizer, switchClient, createNTestFolders, createNTestNotes, createNTestTags, TestApp } = require('./test-utils.js');
const { setupDatabaseAndSynchronizer, switchClient, createNTestFolders, createNTestNotes, createNTestTags, TestApp } = require('@joplin/lib/testing/test-utils.js');
const Setting = require('@joplin/lib/models/Setting').default;
const Folder = require('@joplin/lib/models/Folder').default;
const Note = require('@joplin/lib/models/Note').default;

View File

@@ -1,5 +1,5 @@
/* eslint-disable no-unused-vars */
const { setupDatabaseAndSynchronizer, switchClient, id, ids, sortedIds, at, createNTestFolders, createNTestNotes, createNTestTags, TestApp } = require('./test-utils.js');
const { setupDatabaseAndSynchronizer, switchClient, id, ids, sortedIds, at, createNTestFolders, createNTestNotes, createNTestTags, TestApp } = require('@joplin/lib/testing/test-utils.js');
const Setting = require('@joplin/lib/models/Setting').default;
const Folder = require('@joplin/lib/models/Folder').default;
const Note = require('@joplin/lib/models/Note').default;

View File

@@ -1,5 +1,5 @@
/* eslint-disable no-unused-vars */
const { setupDatabaseAndSynchronizer, switchClient, createNTestFolders, createNTestNotes, createNTestTags, TestApp } = require('./test-utils.js');
const { setupDatabaseAndSynchronizer, switchClient, createNTestFolders, createNTestNotes, createNTestTags, TestApp } = require('@joplin/lib/testing/test-utils.js');
const Setting = require('@joplin/lib/models/Setting').default;
const Folder = require('@joplin/lib/models/Folder').default;
const Note = require('@joplin/lib/models/Note').default;

View File

@@ -1,8 +1,7 @@
import KeychainService from '@joplin/lib/services/keychain/KeychainService';
import shim from '@joplin/lib/shim';
import Setting from '@joplin/lib/models/Setting';
const { db, setupDatabaseAndSynchronizer, switchClient } = require('./test-utils.js');
import { db, setupDatabaseAndSynchronizer, switchClient } from '@joplin/lib/testing/test-utils';
function describeIfCompatible(name: string, fn: any, elseFn: any) {
if (['win32', 'darwin'].includes(shim.platformName())) {

View File

@@ -1,4 +1,4 @@
import PluginRunner from '../app/services/plugins/PluginRunner';
import PluginRunner from '../../../app/services/plugins/PluginRunner';
import PluginService from '@joplin/lib/services/plugins/PluginService';
import { ContentScriptType } from '@joplin/lib/services/plugins/api/types';
import MdToHtml from '@joplin/renderer/MdToHtml';
@@ -7,10 +7,10 @@ import Setting from '@joplin/lib/models/Setting';
import * as fs from 'fs-extra';
import Note from '@joplin/lib/models/Note';
import Folder from '@joplin/lib/models/Folder';
import { newPluginScript } from './test-utils';
import { expectNotThrow, setupDatabaseAndSynchronizer, switchClient, expectThrow, createTempDir } from './test-utils.js';
import { newPluginScript } from '@joplin/lib/testing/test-utils';
import { expectNotThrow, setupDatabaseAndSynchronizer, switchClient, expectThrow, createTempDir, supportDir } from '@joplin/lib/testing/test-utils';
const testPluginDir = `${__dirname}/../tests/support/plugins`;
const testPluginDir = `${supportDir}/plugins`;
function newPluginService(appVersion: string = '1.4') {
const runner = new PluginRunner();
@@ -102,7 +102,7 @@ describe('services_PluginService', function() {
"homepage_url": "https://joplinapp.org"
}
*/
joplin.plugins.register({
onStart: async function() {
await joplin.data.post(['folders'], null, { title: "my plugin folder" });
@@ -141,14 +141,14 @@ describe('services_PluginService', function() {
"not_a_valid_manifest_at_all": 1
}
*/
joplin.plugins.register({
onStart: async function() {},
});
`, `
/* joplin-manifest:
*/
joplin.plugins.register({
onStart: async function() {},
});
@@ -189,7 +189,7 @@ describe('services_PluginService', function() {
"homepage_url": "https://joplinapp.org"
}
*/
joplin.plugins.register({
onStart: async function() {
await joplin.contentScripts.register('markdownItPlugin', 'justtesting', './markdownItTestPlugin.js');
@@ -236,7 +236,7 @@ describe('services_PluginService', function() {
"version": "1.0.0"
}
*/
joplin.plugins.register({
onStart: async function() { },
});
@@ -283,7 +283,7 @@ describe('services_PluginService', function() {
}));
it('should create the data directory', (async () => {
const pluginScript = newPluginScript(`
const pluginScript = newPluginScript(`
joplin.plugins.register({
onStart: async function() {
const dataDir = await joplin.plugins.dataDir();

View File

@@ -1,6 +1,6 @@
import RepositoryApi from '@joplin/lib/services/plugins/RepositoryApi';
import shim from '@joplin/lib/shim';
import { setupDatabaseAndSynchronizer, switchClient, supportDir, createTempDir } from '../../test-utils';
import { setupDatabaseAndSynchronizer, switchClient, supportDir, createTempDir } from '@joplin/lib/testing/test-utils';
async function newRepoApi(): Promise<RepositoryApi> {
const repo = new RepositoryApi(`${supportDir}/pluginRepo`, await createTempDir());

View File

@@ -1,6 +1,6 @@
import Setting from '@joplin/lib/models/Setting';
import PluginService from '@joplin/lib/services/plugins/PluginService';
const { waitForFolderCount, newPluginService, newPluginScript, setupDatabaseAndSynchronizer, switchClient, afterEachCleanUp } = require('../../../test-utils');
const { waitForFolderCount, newPluginService, newPluginScript, setupDatabaseAndSynchronizer, switchClient, afterEachCleanUp } = require('@joplin/lib/testing/test-utils');
import Folder from '@joplin/lib/models/Folder';
describe('JoplinSettings', () => {

View File

@@ -1,6 +1,6 @@
import KeymapService from '@joplin/lib/services/KeymapService';
import PluginService from '@joplin/lib/services/plugins/PluginService';
const { newPluginService, newPluginScript, setupDatabaseAndSynchronizer, switchClient, afterEachCleanUp } = require('../../../test-utils');
const { newPluginService, newPluginScript, setupDatabaseAndSynchronizer, switchClient, afterEachCleanUp } = require('@joplin/lib/testing/test-utils');
describe('JoplinViewMenuItem', () => {

View File

@@ -1,5 +1,5 @@
import Setting from '@joplin/lib/models/Setting';
import { newPluginService, newPluginScript, setupDatabaseAndSynchronizer, switchClient, afterEachCleanUp } from '../../../test-utils';
import { newPluginService, newPluginScript, setupDatabaseAndSynchronizer, switchClient, afterEachCleanUp } from '@joplin/lib/testing/test-utils';
import Note from '@joplin/lib/models/Note';
import Folder from '@joplin/lib/models/Folder';
import ItemChange from '@joplin/lib/models/ItemChange';

View File

@@ -1,6 +1,6 @@
import sandboxProxy, { Target } from '@joplin/lib/services/plugins/sandboxProxy';
const { setupDatabaseAndSynchronizer, switchClient } = require('../../test-utils.js');
const { setupDatabaseAndSynchronizer, switchClient } = require('@joplin/lib/testing/test-utils.js');
describe('services_plugins_sandboxProxy', function() {

View File

@@ -1,4 +1,4 @@
const {main} = require('./syncTargetUtils');
const {main} = require('@joplin/lib/testing/syncTargetUtils');
const syncTargetType = process.argv.length <= 2 ? 'normal' : process.argv[2];

View File

@@ -31,7 +31,7 @@ if [ "$RESET_ALL" == "1" ]; then
echo "config sync.9.password 123456" >> "$CMD_FILE"
if [ "$1" == "1" ]; then
curl --data '{"action": "createTestUsers"}' http://localhost:22300/api/debug
curl --data '{"action": "createTestUsers"}' -H 'Content-Type: application/json' http://localhost:22300/api/debug
echo 'mkbook "shared"' >> "$CMD_FILE"
echo 'mkbook "other"' >> "$CMD_FILE"

View File

@@ -240,7 +240,7 @@ PODS:
- React-cxxreact (= 0.63.3)
- React-jsi (= 0.63.3)
- React-jsinspector (0.63.3)
- react-native-alarm-notification (1.7.1):
- react-native-alarm-notification (1.0.3):
- React
- react-native-camera (3.40.0):
- React-Core
@@ -391,7 +391,7 @@ DEPENDENCIES:
- React-jsi (from `../node_modules/react-native/ReactCommon/jsi`)
- React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`)
- React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`)
- react-native-alarm-notification (from `../node_modules/react-native-alarm-notification`)
- react-native-alarm-notification (from `../node_modules/joplin-rn-alarm-notification`)
- react-native-camera (from `../node_modules/react-native-camera`)
- react-native-document-picker (from `../node_modules/react-native-document-picker`)
- "react-native-geolocation (from `../node_modules/@react-native-community/geolocation`)"
@@ -475,7 +475,7 @@ EXTERNAL SOURCES:
React-jsinspector:
:path: "../node_modules/react-native/ReactCommon/jsinspector"
react-native-alarm-notification:
:path: "../node_modules/react-native-alarm-notification"
:path: "../node_modules/joplin-rn-alarm-notification"
react-native-camera:
:path: "../node_modules/react-native-camera"
react-native-document-picker:
@@ -568,7 +568,7 @@ SPEC CHECKSUMS:
React-jsi: df07aa95b39c5be3e41199921509bfa929ed2b9d
React-jsiexecutor: b56c03e61c0dd5f5801255f2160a815f4a53d451
React-jsinspector: 8e68ffbfe23880d3ee9bafa8be2777f60b25cbe2
react-native-alarm-notification: 8f2adb4521bf7ca867278d4c236553e154dbbbc6
react-native-alarm-notification: 466e4ad56fbd948ecac26e657f292dca8bf483d5
react-native-camera: 5c1fbfecf63b802b8ca4a71c60d30a71550fb348
react-native-document-picker: b3e78a8f7fef98b5cb069f20fc35797d55e68e28
react-native-geolocation: cbd9d6bd06bac411eed2671810f454d4908484a8

View File

@@ -1,9 +1,4 @@
/* eslint-disable no-unused-vars */
const time = require('@joplin/lib/time').default;
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const ArrayUtils = require('@joplin/lib/ArrayUtils');
const ArrayUtils = require('./ArrayUtils');
describe('ArrayUtils', function() {

View File

@@ -1,5 +1,5 @@
import InMemoryCache from '@joplin/lib/InMemoryCache';
import time from '@joplin/lib/time';
import InMemoryCache from './InMemoryCache';
import time from './time';
describe('InMemoryCache', function() {

View File

@@ -1,6 +1,6 @@
/* eslint-disable no-unused-vars */
const StringUtils = require('@joplin/lib/string-utils');
const StringUtils = require('./string-utils');
describe('StringUtils', function() {

View File

@@ -1,8 +1,5 @@
/* eslint-disable no-unused-vars */
const { fileContentEqual, setupDatabase, revisionService, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const TaskQueue = require('@joplin/lib/TaskQueue.js');
const { setupDatabaseAndSynchronizer, sleep, switchClient } = require('./testing/test-utils.js');
const TaskQueue = require('./TaskQueue.js');
describe('TaskQueue', function() {

View File

@@ -0,0 +1,22 @@
const { setupDatabaseAndSynchronizer, switchClient } = require('./testing/test-utils.js');
const BaseModel = require('./BaseModel').default;
describe('database', function() {
beforeEach(async (done) => {
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
});
it('should not modify cached field names', (async () => {
const db = BaseModel.db();
const fieldNames = db.tableFieldNames('notes');
const fieldCount = fieldNames.length;
fieldNames.push('type_');
expect(fieldCount).toBeGreaterThan(0);
expect(db.tableFieldNames('notes').length).toBe(fieldCount);
}));
});

View File

@@ -1,8 +1,8 @@
'use strict';
const { checkThrow } = require('./test-utils.js');
const eventManager = require('@joplin/lib/eventManager').default;
const { checkThrow } = require('./testing/test-utils.js');
const eventManager = require('./eventManager').default;
describe('eventManager', function() {

View File

@@ -1,4 +1,4 @@
import { afterAllCleanUp, setupDatabaseAndSynchronizer, switchClient, fileApi } from './test-utils';
import { afterAllCleanUp, setupDatabaseAndSynchronizer, switchClient, fileApi } from './testing/test-utils';
describe('file-api-driver', function() {

View File

@@ -1,6 +1,6 @@
import FsDriverNode from '@joplin/lib/fs-driver-node';
import shim from '@joplin/lib/shim';
const { expectThrow } = require('./test-utils.js');
import FsDriverNode from './fs-driver-node';
import shim from './shim';
const { expectThrow } = require('./testing/test-utils.js');
// On Windows, path.resolve is going to convert a path such as
// /tmp/file.txt to c:\tmp\file.txt

View File

@@ -1,4 +1,4 @@
import htmlUtils from '@joplin/lib/htmlUtils';
import htmlUtils from './htmlUtils';
describe('htmlUtils', function() {

View File

@@ -1,17 +1,17 @@
import { NoteEntity, ResourceEntity, TagEntity } from '@joplin/lib/services/database/types';
import shim from '@joplin/lib/shim';
import { NoteEntity, ResourceEntity, TagEntity } from './services/database/types';
import shim from './shim';
const fs = require('fs-extra');
const os = require('os');
const { filename } = require('@joplin/lib/path-utils');
const { setupDatabaseAndSynchronizer, switchClient, expectNotThrow } = require('./test-utils.js');
const { enexXmlToMd } = require('@joplin/lib/import-enex-md-gen.js');
const { importEnex } = require('@joplin/lib/import-enex');
import Note from '@joplin/lib/models/Note';
import Tag from '@joplin/lib/models/Tag';
import Resource from '@joplin/lib/models/Resource';
const { filename } = require('./path-utils');
const { setupDatabaseAndSynchronizer, switchClient, expectNotThrow, supportDir } = require('./testing/test-utils.js');
const { enexXmlToMd } = require('./import-enex-md-gen.js');
const { importEnex } = require('./import-enex');
import Note from './models/Note';
import Tag from './models/Tag';
import Resource from './models/Resource';
const enexSampleBaseDir = `${__dirname}/enex_to_md`;
const enexSampleBaseDir = `${supportDir}/../enex_to_md`;
describe('EnexToMd', function() {

View File

@@ -10,4 +10,7 @@ module.exports = {
],
testEnvironment: 'node',
setupFilesAfterEnv: [`${__dirname}/jest.setup.js`],
slowTestThreshold: 40,
};

View File

@@ -0,0 +1,9 @@
const { afterEachCleanUp } = require('./testing/test-utils.js');
const { shimInit } = require('./shim-init-node.js');
const sharp = require('sharp');
shimInit(sharp, null);
global.afterEach(async () => {
await afterEachCleanUp();
});

View File

@@ -1,6 +1,6 @@
/* eslint-disable no-unused-vars */
const markdownUtils = require('@joplin/lib/markdownUtils').default;
const markdownUtils = require('./markdownUtils').default;
describe('markdownUtils', function() {

View File

@@ -1,9 +1,4 @@
/* eslint-disable no-unused-vars */
const time = require('@joplin/lib/time').default;
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const mimeUtils = require('@joplin/lib/mime-utils.js').mime;
const mimeUtils = require('./mime-utils.js').mime;
describe('mimeUils', function() {

View File

@@ -1,20 +1,6 @@
/* eslint-disable no-unused-vars */
const time = require('@joplin/lib/time').default;
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const Folder = require('@joplin/lib/models/Folder').default;
const Note = require('@joplin/lib/models/Note').default;
const BaseItem = require('@joplin/lib/models/BaseItem').default;
const Resource = require('@joplin/lib/models/Resource').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
const shim = require('@joplin/lib/shim').default;
async function allItems() {
const folders = await Folder.all();
const notes = await Note.all();
return folders.concat(notes);
}
const { setupDatabaseAndSynchronizer, switchClient } = require('../testing/test-utils.js');
const Folder = require('../models/Folder').default;
const Note = require('../models/Note').default;
describe('models_BaseItem', function() {

View File

@@ -1,13 +1,13 @@
import { setupDatabaseAndSynchronizer, switchClient, createFolderTree } from './test-utils';
import Folder from '@joplin/lib/models/Folder';
import { allNotesFolders } from './test-utils-synchronizer';
import Note from '@joplin/lib/models/Note';
import shim from '@joplin/lib/shim';
import Resource from '@joplin/lib/models/Resource';
import { FolderEntity, NoteEntity, ResourceEntity } from '@joplin/lib/services/database/types';
import ResourceService from '@joplin/lib/services/ResourceService';
import { setupDatabaseAndSynchronizer, switchClient, createFolderTree, supportDir } from '../testing/test-utils';
import Folder from '../models/Folder';
import { allNotesFolders } from '../testing/test-utils-synchronizer';
import Note from '../models/Note';
import shim from '../shim';
import Resource from '../models/Resource';
import { FolderEntity, NoteEntity, ResourceEntity } from '../services/database/types';
import ResourceService from '../services/ResourceService';
const testImagePath = `${__dirname}/../tests/support/photo.jpg`;
const testImagePath = `${supportDir}/photo.jpg`;
describe('models_Folder.sharing', function() {

View File

@@ -1,7 +1,7 @@
import { FolderEntity } from '@joplin/lib/services/database/types';
import { createNTestNotes, setupDatabaseAndSynchronizer, sleep, switchClient, checkThrowAsync, createFolderTree } from './test-utils';
import Folder from '@joplin/lib/models/Folder';
import Note from '@joplin/lib/models/Note';
import { FolderEntity } from '../services/database/types';
import { createNTestNotes, setupDatabaseAndSynchronizer, sleep, switchClient, checkThrowAsync, createFolderTree } from '../testing/test-utils';
import Folder from './Folder';
import Note from './Note';
async function allItems() {
const folders = await Folder.all();

View File

@@ -1,14 +1,9 @@
/* eslint-disable no-unused-vars */
const time = require('@joplin/lib/time').default;
const { fileContentEqual, revisionService, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const SearchEngine = require('@joplin/lib/services/searchengine/SearchEngine').default;
const ResourceService = require('@joplin/lib/services/ResourceService').default;
const ItemChangeUtils = require('@joplin/lib/services/ItemChangeUtils').default;
const Note = require('@joplin/lib/models/Note').default;
const Setting = require('@joplin/lib/models/Setting').default;
const ItemChange = require('@joplin/lib/models/ItemChange').default;
const { revisionService, setupDatabaseAndSynchronizer, db, switchClient } = require('../testing/test-utils.js');
const SearchEngine = require('../services/searchengine/SearchEngine').default;
const ResourceService = require('../services/ResourceService').default;
const ItemChangeUtils = require('../services/ItemChangeUtils').default;
const Note = require('../models/Note').default;
const ItemChange = require('../models/ItemChange').default;
let searchEngine = null;
@@ -23,7 +18,7 @@ describe('models_ItemChange', function() {
});
it('should delete old changes that have been processed', (async () => {
const n1 = await Note.save({ title: 'abcd efgh' }); // 3
await Note.save({ title: 'abcd efgh' });
await ItemChange.waitForAllSaved();

View File

@@ -1,12 +1,12 @@
import Setting from '@joplin/lib/models/Setting';
import BaseModel from '@joplin/lib/BaseModel';
import shim from '@joplin/lib/shim';
import markdownUtils from '@joplin/lib/markdownUtils';
const { sortedIds, createNTestNotes, setupDatabaseAndSynchronizer, switchClient, checkThrowAsync } = require('./test-utils.js');
import Folder from '@joplin/lib/models/Folder';
import Note from '@joplin/lib/models/Note';
import Tag from '@joplin/lib/models/Tag';
const ArrayUtils = require('@joplin/lib/ArrayUtils.js');
import Setting from './Setting';
import BaseModel from '../BaseModel';
import shim from '../shim';
import markdownUtils from '../markdownUtils';
import { sortedIds, createNTestNotes, setupDatabaseAndSynchronizer, switchClient, checkThrowAsync, supportDir } from '../testing/test-utils';
import Folder from './Folder';
import Note from './Note';
import Tag from './Tag';
const ArrayUtils = require('../ArrayUtils.js');
async function allItems() {
const folders = await Folder.all();
@@ -30,15 +30,15 @@ describe('models_Note', function() {
expect(items.length).toBe(1);
expect(items[0].id).toBe(note1.id);
await shim.attachFileToNote(note2, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note2, `${supportDir}/photo.jpg`);
note2 = await Note.load(note2.id);
items = await Note.linkedItems(note2.body);
expect(items.length).toBe(2);
expect(items[0].type_).toBe(BaseModel.TYPE_NOTE);
expect(items[1].type_).toBe(BaseModel.TYPE_RESOURCE);
const resource2 = await shim.createResourceFromPath(`${__dirname}/../tests/support/photo.jpg`);
const resource3 = await shim.createResourceFromPath(`${__dirname}/../tests/support/photo.jpg`);
const resource2 = await shim.createResourceFromPath(`${supportDir}/photo.jpg`);
const resource3 = await shim.createResourceFromPath(`${supportDir}/photo.jpg`);
note2.body += `<img alt="bla" src=":/${resource2.id}"/>`;
note2.body += `<img src=':/${resource3.id}' />`;
items = await Note.linkedItems(note2.body);
@@ -228,9 +228,9 @@ describe('models_Note', function() {
it('should convert resource paths from internal to external paths', (async () => {
const resourceDirName = Setting.value('resourceDirName');
const resourceDir = Setting.value('resourceDir');
const r1 = await shim.createResourceFromPath(`${__dirname}/../tests/support/photo.jpg`);
const r2 = await shim.createResourceFromPath(`${__dirname}/../tests/support/photo.jpg`);
const r3 = await shim.createResourceFromPath(`${__dirname}/../tests/support/welcome.pdf`);
const r1 = await shim.createResourceFromPath(`${supportDir}/photo.jpg`);
const r2 = await shim.createResourceFromPath(`${supportDir}/photo.jpg`);
const r3 = await shim.createResourceFromPath(`${supportDir}/welcome.pdf`);
const note1 = await Note.save({ title: 'note1' });
const t1 = r1.updated_time;
const t2 = r2.updated_time;

View File

@@ -1,20 +1,7 @@
/* eslint-disable no-unused-vars */
const time = require('@joplin/lib/time').default;
const { sortedIds, createNTestNotes, fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const Folder = require('@joplin/lib/models/Folder').default;
const Note = require('@joplin/lib/models/Note').default;
const Setting = require('@joplin/lib/models/Setting').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
const ArrayUtils = require('@joplin/lib/ArrayUtils.js');
const shim = require('@joplin/lib/shim').default;
async function allItems() {
const folders = await Folder.all();
const notes = await Note.all();
return folders.concat(notes);
}
const time = require('../time').default;
const { setupDatabaseAndSynchronizer, switchClient } = require('../testing/test-utils.js');
const Folder = require('../models/Folder').default;
const Note = require('../models/Note').default;
describe('models_Note_CustomSortOrder', function() {
beforeEach(async (done) => {

View File

@@ -1,15 +1,10 @@
/* eslint-disable no-unused-vars, require-atomic-updates */
const { supportDir, setupDatabaseAndSynchronizer, switchClient } = require('../testing/test-utils.js');
const Folder = require('../models/Folder').default;
const Note = require('../models/Note').default;
const Resource = require('../models/Resource').default;
const shim = require('../shim').default;
const time = require('@joplin/lib/time').default;
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const Folder = require('@joplin/lib/models/Folder').default;
const Note = require('@joplin/lib/models/Note').default;
const Resource = require('@joplin/lib/models/Resource').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
const shim = require('@joplin/lib/shim').default;
const testImagePath = `${__dirname}/../tests/support/photo.jpg`;
const testImagePath = `${supportDir}/photo.jpg`;
describe('models_Resource', function() {

View File

@@ -1,15 +1,6 @@
/* eslint-disable no-unused-vars */
const time = require('@joplin/lib/time').default;
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const Folder = require('@joplin/lib/models/Folder').default;
const Note = require('@joplin/lib/models/Note').default;
const NoteTag = require('@joplin/lib/models/NoteTag').default;
const Tag = require('@joplin/lib/models/Tag').default;
const Revision = require('@joplin/lib/models/Revision').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
const shim = require('@joplin/lib/shim').default;
const { setupDatabaseAndSynchronizer, switchClient } = require('../testing/test-utils.js');
const Note = require('../models/Note').default;
const Revision = require('../models/Revision').default;
describe('models_Revision', function() {

View File

@@ -1,7 +1,7 @@
import Setting, { SettingSectionSource } from '@joplin/lib/models/Setting';
import { setupDatabaseAndSynchronizer, switchClient, expectThrow, expectNotThrow, msleep } from './test-utils';
import Setting, { SettingSectionSource } from '../models/Setting';
import { setupDatabaseAndSynchronizer, switchClient, expectThrow, expectNotThrow, msleep } from '../testing/test-utils';
import * as fs from 'fs-extra';
import Logger from '@joplin/lib/Logger';
import Logger from '../Logger';
async function loadSettingsFromFile(): Promise<any> {
return JSON.parse(await fs.readFile(Setting.settingFilePath, 'utf8'));

View File

@@ -1,14 +1,7 @@
/* eslint-disable no-unused-vars */
const time = require('@joplin/lib/time').default;
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const Folder = require('@joplin/lib/models/Folder').default;
const Note = require('@joplin/lib/models/Note').default;
const NoteTag = require('@joplin/lib/models/NoteTag').default;
const Tag = require('@joplin/lib/models/Tag').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
const shim = require('@joplin/lib/shim').default;
const { setupDatabaseAndSynchronizer, switchClient, checkThrowAsync } = require('../testing/test-utils.js');
const Folder = require('../models/Folder').default;
const Note = require('../models/Note').default;
const Tag = require('../models/Tag').default;
describe('models_Tag', function() {
@@ -97,7 +90,7 @@ describe('models_Tag', function() {
const taga = await Tag.save({ title: 'mytaga' });
const tagb = await Tag.save({ title: 'mytagb' });
const tagc = await Tag.save({ title: 'mytagc' });
const tagd = await Tag.save({ title: 'mytagd' });
await Tag.save({ title: 'mytagd' });
const note0 = await Note.save({ title: 'ma note 0', parent_id: folder1.id });
const note1 = await Note.save({ title: 'ma note 1', parent_id: folder1.id });

View File

@@ -1,5 +1,5 @@
import Setting from '@joplin/lib/models/Setting';
import time from '@joplin/lib/time';
import Setting from '../models/Setting';
import time from '../time';
describe('dateFormats', function() {

View File

@@ -777,6 +777,15 @@
"@babel/types": "^7.3.0"
}
},
"@types/fs-extra": {
"version": "9.0.11",
"resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.11.tgz",
"integrity": "sha512-mZsifGG4QeQ7hlkhO56u7zt/ycBgGxSVsFI/6lGTU34VtwkiqrrSDgw0+ygs8kFGWcXnFQWMrzF2h7TtDFNixA==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/graceful-fs": {
"version": "4.1.4",
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.4.tgz",
@@ -1014,6 +1023,12 @@
"typical": "^2.6.1"
}
},
"array-flatten": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-3.0.0.tgz",
"integrity": "sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==",
"dev": true
},
"array-unique": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
@@ -1265,6 +1280,40 @@
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz",
"integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ=="
},
"bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
"dev": true,
"requires": {
"buffer": "^5.5.0",
"inherits": "^2.0.4",
"readable-stream": "^3.4.0"
},
"dependencies": {
"buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"dev": true,
"requires": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"dev": true,
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
}
}
},
"block-stream": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz",
@@ -1494,6 +1543,16 @@
"source-map": "~0.6.0"
}
},
"clean-html": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/clean-html/-/clean-html-1.5.0.tgz",
"integrity": "sha512-eDu0vN44ZBvoEU0oRIKwWPIccGWXtdnUNmKJuTukZ1de00Uoqavb5pfIMKiC7/r+knQ5RbvAjGuVZiN3JwJL4Q==",
"dev": true,
"requires": {
"htmlparser2": "^3.8.2",
"minimist": "^1.1.1"
}
},
"cliss": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/cliss/-/cliss-0.0.2.tgz",
@@ -1788,6 +1847,15 @@
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
},
"decompress-response": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
"integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
"dev": true,
"requires": {
"mimic-response": "^2.0.0"
}
},
"deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
@@ -1882,6 +1950,55 @@
"integrity": "sha512-Mv/TDa3nZ9sbc5soK+OoA74BsS3mL37yixCvUAQkiuA4Wz6YtwP/K47n2rv2ovzHZvoiQeA5FTQOschKkEwB0Q==",
"dev": true
},
"dom-serializer": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
"integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
"dev": true,
"requires": {
"domelementtype": "^2.0.1",
"entities": "^2.0.0"
},
"dependencies": {
"domelementtype": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
"integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
"dev": true
},
"entities": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
"dev": true
}
}
},
"domelementtype": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
"integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
"dev": true
},
"domhandler": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
"integrity": "sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==",
"dev": true,
"requires": {
"domelementtype": "1"
}
},
"domutils": {
"version": "1.7.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
"integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
"dev": true,
"requires": {
"dom-serializer": "0",
"domelementtype": "1"
}
},
"ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
@@ -1930,6 +2047,12 @@
"once": "^1.4.0"
}
},
"entities": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz",
"integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==",
"dev": true
},
"error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
@@ -2071,6 +2194,12 @@
}
}
},
"expand-template": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
"dev": true
},
"expect": {
"version": "26.6.2",
"resolved": "https://registry.npmjs.org/expect/-/expect-26.6.2.tgz",
@@ -2284,6 +2413,12 @@
"map-cache": "^0.2.2"
}
},
"fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
"dev": true
},
"fs-extra": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz",
@@ -2404,6 +2539,12 @@
"assert-plus": "^1.0.0"
}
},
"github-from-package": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
"integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=",
"dev": true
},
"glob": {
"version": "7.1.6",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
@@ -2563,6 +2704,33 @@
"uglify-js": "3.4.x"
}
},
"htmlparser2": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.10.1.tgz",
"integrity": "sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ==",
"dev": true,
"requires": {
"domelementtype": "^1.3.1",
"domhandler": "^2.3.0",
"domutils": "^1.5.1",
"entities": "^1.1.1",
"inherits": "^2.0.1",
"readable-stream": "^3.1.1"
},
"dependencies": {
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"dev": true,
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
}
}
},
"http-errors": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.0.tgz",
@@ -3994,6 +4162,15 @@
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
"integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw="
},
"lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"requires": {
"yallist": "^4.0.0"
}
},
"magicli": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/magicli/-/magicli-0.0.8.tgz",
@@ -4120,6 +4297,12 @@
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
"dev": true
},
"mimic-response": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
"integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==",
"dev": true
},
"minimatch": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@@ -4162,6 +4345,12 @@
"minimist": "^1.2.5"
}
},
"mkdirp-classic": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
"dev": true
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
@@ -4219,6 +4408,12 @@
}
}
},
"napi-build-utils": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
"integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
"dev": true
},
"natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
@@ -4249,6 +4444,23 @@
"lower-case": "^1.1.1"
}
},
"node-abi": {
"version": "2.26.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.26.0.tgz",
"integrity": "sha512-ag/Vos/mXXpWLLAYWsAoQdgS+gW7IwvgMLOgqopm/DbzAjazLltzgzpVMsFlgmo9TzG5hGXeaBZx2AI731RIsQ==",
"dev": true,
"requires": {
"semver": "^5.4.1"
},
"dependencies": {
"semver": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
"dev": true
}
}
},
"node-addon-api": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.0.tgz",
@@ -4387,6 +4599,12 @@
}
}
},
"noop-logger": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/noop-logger/-/noop-logger-0.1.1.tgz",
"integrity": "sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=",
"dev": true
},
"nopt": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz",
@@ -4788,6 +5006,28 @@
"integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=",
"dev": true
},
"prebuild-install": {
"version": "6.1.2",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.2.tgz",
"integrity": "sha512-PzYWIKZeP+967WuKYXlTOhYBgGOvTRSfaKI89XnfJ0ansRAH7hDU45X+K+FZeI1Wb/7p/NnuctPH3g0IqKUuSQ==",
"dev": true,
"requires": {
"detect-libc": "^1.0.3",
"expand-template": "^2.0.3",
"github-from-package": "0.0.0",
"minimist": "^1.2.3",
"mkdirp-classic": "^0.5.3",
"napi-build-utils": "^1.0.1",
"node-abi": "^2.21.0",
"noop-logger": "^0.1.1",
"npmlog": "^4.0.1",
"pump": "^3.0.0",
"rc": "^1.2.7",
"simple-get": "^3.0.3",
"tar-fs": "^2.0.0",
"tunnel-agent": "^0.6.0"
}
},
"prelude-ls": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
@@ -5440,6 +5680,77 @@
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
"sharp": {
"version": "0.26.3",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.26.3.tgz",
"integrity": "sha512-NdEJ9S6AMr8Px0zgtFo1TJjMK/ROMU92MkDtYn2BBrDjIx3YfH9TUyGdzPC+I/L619GeYQc690Vbaxc5FPCCWg==",
"dev": true,
"requires": {
"array-flatten": "^3.0.0",
"color": "^3.1.3",
"detect-libc": "^1.0.3",
"node-addon-api": "^3.0.2",
"npmlog": "^4.1.2",
"prebuild-install": "^6.0.0",
"semver": "^7.3.2",
"simple-get": "^4.0.0",
"tar-fs": "^2.1.1",
"tunnel-agent": "^0.6.0"
},
"dependencies": {
"color": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz",
"integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==",
"dev": true,
"requires": {
"color-convert": "^1.9.1",
"color-string": "^1.5.4"
}
},
"decompress-response": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
"dev": true,
"requires": {
"mimic-response": "^3.1.0"
}
},
"mimic-response": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
"dev": true
},
"node-addon-api": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.0.tgz",
"integrity": "sha512-kcwSAWhPi4+QzAtsL2+2s/awvDo2GKLsvMCwNRxb5BUshteXU8U97NCyvQDsGKs/m0He9WcG4YWew/BnuLx++w==",
"dev": true
},
"semver": {
"version": "7.3.5",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz",
"integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==",
"dev": true,
"requires": {
"lru-cache": "^6.0.0"
}
},
"simple-get": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.0.tgz",
"integrity": "sha512-ZalZGexYr3TA0SwySsr5HlgOOinS4Jsa8YB2GJ6lUNAazyAu4KG/VmzMTwAt2YVXzzVj8QmefmAonZIK2BSGcQ==",
"dev": true,
"requires": {
"decompress-response": "^6.0.0",
"once": "^1.3.1",
"simple-concat": "^1.0.0"
}
}
}
},
"shebang-command": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
@@ -5465,6 +5776,23 @@
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
},
"simple-concat": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
"dev": true
},
"simple-get": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz",
"integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==",
"dev": true,
"requires": {
"decompress-response": "^4.2.0",
"once": "^1.3.1",
"simple-concat": "^1.0.0"
}
},
"simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
@@ -6029,6 +6357,44 @@
}
}
},
"tar-fs": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
"integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
"dev": true,
"requires": {
"chownr": "^1.1.1",
"mkdirp-classic": "^0.5.2",
"pump": "^3.0.0",
"tar-stream": "^2.1.4"
}
},
"tar-stream": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
"dev": true,
"requires": {
"bl": "^4.0.3",
"end-of-stream": "^1.4.1",
"fs-constants": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^3.1.1"
},
"dependencies": {
"readable-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
"dev": true,
"requires": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
}
}
}
},
"tcp-port-used": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/tcp-port-used/-/tcp-port-used-0.1.2.tgz",
@@ -6600,6 +6966,12 @@
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
"dev": true
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"yargs": {
"version": "15.4.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",

View File

@@ -18,8 +18,11 @@
"devDependencies": {
"@types/jest": "^26.0.15",
"@types/node": "^14.14.6",
"@types/fs-extra": "^9.0.6",
"jest": "^26.6.3",
"typescript": "^4.0.5"
"sharp": "^0.26.2",
"typescript": "^4.0.5",
"clean-html": "^1.5.0"
},
"dependencies": {
"@joplin/fork-htmlparser2": "^4.1.24",

View File

@@ -1,8 +1,4 @@
/* eslint-disable no-unused-vars */
const { extractExecutablePath, quotePath, unquotePath, friendlySafeFilename, toFileProtocolPath } = require('@joplin/lib/path-utils');
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const { extractExecutablePath, quotePath, unquotePath, friendlySafeFilename, toFileProtocolPath } = require('./path-utils');
describe('pathUtils', function() {

View File

@@ -1,12 +1,7 @@
/* eslint-disable no-unused-vars */
const { setupDatabaseAndSynchronizer, switchClient, createNTestNotes, createNTestFolders, createNTestTags } = require('./test-utils.js');
const Folder = require('@joplin/lib/models/Folder').default;
const Note = require('@joplin/lib/models/Note').default;
const Tag = require('@joplin/lib/models/Tag').default;
const reducer = require('@joplin/lib/reducer').default;
const { defaultState, stateUtils, MAX_HISTORY } = require('@joplin/lib/reducer');
const { ALL_NOTES_FILTER_ID } = require('@joplin/lib/reserved-ids');
const { setupDatabaseAndSynchronizer, switchClient, createNTestNotes, createNTestFolders, createNTestTags } = require('./testing/test-utils.js');
const reducer = require('./reducer').default;
const { defaultState, MAX_HISTORY } = require('./reducer');
const { ALL_NOTES_FILTER_ID } = require('./reserved-ids');
function initTestState(folders, selectedFolderIndex, notes, selectedNoteIndexes, tags = null, selectedTagIndex = null) {
let state = defaultState;
@@ -86,19 +81,13 @@ function getIds(items, indexes = null) {
return ids;
}
let insideBeforeEach = false;
describe('reducer', function() {
beforeEach(async (done) => {
insideBeforeEach = true;
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
done();
insideBeforeEach = false;
});
// tests for NOTE_DELETE
@@ -560,7 +549,6 @@ describe('reducer', function() {
// select the 1st folder and the 1st note
let state = initTestState(folders, 0, notes, [0]);
const idx = 0;
for (let i = 0; i < 2 * MAX_HISTORY; i++) {
state = goToNote(notes, [i % 5], state);
}

View File

@@ -1,5 +1,5 @@
import Setting from '@joplin/lib/models/Setting';
import { reg } from '@joplin/lib/registry';
import Setting from './models/Setting';
import { reg } from './registry';
const sync = {
start: jest.fn().mockReturnValue({}),

View File

@@ -1,10 +1,10 @@
import MenuUtils from '@joplin/lib/services/commands/MenuUtils';
import ToolbarButtonUtils from '@joplin/lib/services/commands/ToolbarButtonUtils';
import CommandService, { CommandDeclaration, CommandRuntime } from '@joplin/lib/services/CommandService';
import stateToWhenClauseContext from '@joplin/lib/services/commands/stateToWhenClauseContext';
import KeymapService from '@joplin/lib/services/KeymapService';
import MenuUtils from '../services/commands/MenuUtils';
import ToolbarButtonUtils from '../services/commands/ToolbarButtonUtils';
import CommandService, { CommandDeclaration, CommandRuntime } from '../services/CommandService';
import stateToWhenClauseContext from '../services/commands/stateToWhenClauseContext';
import KeymapService from '../services/KeymapService';
const { setupDatabaseAndSynchronizer, switchClient, expectThrow, expectNotThrow } = require('./test-utils.js');
const { setupDatabaseAndSynchronizer, switchClient, expectThrow, expectNotThrow } = require('../testing/test-utils.js');
interface TestCommand {
declaration: CommandDeclaration;

View File

@@ -1,18 +1,12 @@
/* eslint-disable no-unused-vars */
/* eslint-disable no-unused-vars, @typescript-eslint/no-unused-vars, prefer-const */
const time = require('@joplin/lib/time').default;
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const Folder = require('@joplin/lib/models/Folder').default;
const Note = require('@joplin/lib/models/Note').default;
const Tag = require('@joplin/lib/models/Tag').default;
const Database = require('@joplin/lib/database').default;
const Setting = require('@joplin/lib/models/Setting').default;
const BaseItem = require('@joplin/lib/models/BaseItem').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
const MasterKey = require('@joplin/lib/models/MasterKey').default;
const SyncTargetRegistry = require('@joplin/lib/SyncTargetRegistry.js');
const EncryptionService = require('@joplin/lib/services/EncryptionService').default;
const { fileContentEqual, setupDatabaseAndSynchronizer, supportDir, switchClient, objectsEqual, checkThrowAsync } = require('../testing/test-utils.js');
const Folder = require('../models/Folder').default;
const Note = require('../models/Note').default;
const Setting = require('../models/Setting').default;
const BaseItem = require('../models/BaseItem').default;
const MasterKey = require('../models/MasterKey').default;
const EncryptionService = require('../services/EncryptionService').default;
let service = null;
@@ -256,7 +250,7 @@ describe('services_EncryptionService', function() {
masterKey = await MasterKey.save(masterKey);
await service.loadMasterKey_(masterKey, '123456', true);
const sourcePath = `${__dirname}/../tests/support/photo.jpg`;
const sourcePath = `${supportDir}/photo.jpg`;
const encryptedPath = `${Setting.value('tempDir')}/photo.crypted`;
const decryptedPath = `${Setting.value('tempDir')}/photo.jpg`;

View File

@@ -1,6 +1,6 @@
const { tempFilePath } = require('./test-utils.js');
const KeymapService = require('@joplin/lib/services/KeymapService').default;
const { tempFilePath } = require('../testing/test-utils.js');
const KeymapService = require('../services/KeymapService').default;
const keymapService = KeymapService.instance();
keymapService.initialize([]);

View File

@@ -1,8 +1,5 @@
/* eslint-disable no-unused-vars */
const { fileContentEqual, setupDatabase, revisionService, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const KvStore = require('@joplin/lib/services/KvStore').default;
const { setupDatabaseAndSynchronizer, db, switchClient } = require('../testing/test-utils.js');
const KvStore = require('../services/KvStore').default;
function setupStore() {
const store = KvStore.instance();

View File

@@ -1,13 +1,13 @@
import time from '@joplin/lib/time';
import NoteResource from '@joplin/lib/models/NoteResource';
import ResourceService from '@joplin/lib/services/ResourceService';
import shim from '@joplin/lib/shim';
import time from '../time';
import NoteResource from '../models/NoteResource';
import ResourceService from '../services/ResourceService';
import shim from '../shim';
const { resourceService, decryptionWorker, encryptionService, loadEncryptionMasterKey, allSyncTargetItemsEncrypted, setupDatabaseAndSynchronizer, db, synchronizer, switchClient } = require('./test-utils.js');
import Folder from '@joplin/lib/models/Folder';
import Note from '@joplin/lib/models/Note';
import Resource from '@joplin/lib/models/Resource';
import SearchEngine from '@joplin/lib/services/searchengine/SearchEngine';
const { resourceService, decryptionWorker, supportDir, encryptionService, loadEncryptionMasterKey, allSyncTargetItemsEncrypted, setupDatabaseAndSynchronizer, db, synchronizer, switchClient } = require('../testing/test-utils.js');
import Folder from '../models/Folder';
import Note from '../models/Note';
import Resource from '../models/Resource';
import SearchEngine from '../services/searchengine/SearchEngine';
describe('services_ResourceService', function() {
@@ -23,7 +23,7 @@ describe('services_ResourceService', function() {
const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
note1 = await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
const resource1 = (await Resource.all())[0];
const resourcePath = Resource.fullPath(resource1);
@@ -55,7 +55,7 @@ describe('services_ResourceService', function() {
const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
const note2 = await Note.save({ title: 'ma deuxième note', parent_id: folder1.id });
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
note1 = await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
const resource1 = (await Resource.all())[0];
await service.indexNoteResources();
@@ -75,7 +75,7 @@ describe('services_ResourceService', function() {
it('should not delete a resource that has never been associated with any note, because it probably means the resource came via sync, and associated note has not arrived yet', (async () => {
const service = new ResourceService();
await shim.createResourceFromPath(`${__dirname}/../tests/support/photo.jpg`);
await shim.createResourceFromPath(`${supportDir}/photo.jpg`);
await service.indexNoteResources();
await service.deleteOrphanResources(0);
@@ -88,7 +88,7 @@ describe('services_ResourceService', function() {
const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
note1 = await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
const resource1 = (await Resource.all())[0];
await service.indexNoteResources();
@@ -107,7 +107,7 @@ describe('services_ResourceService', function() {
const folder1 = await Folder.save({ title: 'folder1' });
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
await service.indexNoteResources();
@@ -143,7 +143,7 @@ describe('services_ResourceService', function() {
await encryptionService().loadMasterKeysFromSettings();
const folder1 = await Folder.save({ title: 'folder1' });
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`); // R1
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`); // R1
await resourceService().indexNoteResources();
await synchronizer().start();
expect(await allSyncTargetItemsEncrypted()).toBe(true);
@@ -156,7 +156,7 @@ describe('services_ResourceService', function() {
await decryptionWorker().start();
{
const n1 = await Note.load(note1.id);
await shim.attachFileToNote(n1, `${__dirname}/../tests/support/photo.jpg`); // R2
await shim.attachFileToNote(n1, `${supportDir}/photo.jpg`); // R2
}
await synchronizer().start();
@@ -173,7 +173,7 @@ describe('services_ResourceService', function() {
const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
note1 = await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
note1 = await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
await resourceService().indexNoteResources();
const bodyWithResource = note1.body;
await Note.save({ id: note1.id, body: '' });
@@ -198,7 +198,7 @@ describe('services_ResourceService', function() {
// const service = new ResourceService();
// let note = await Note.save({});
// note = await shim.attachFileToNote(note, `${__dirname}/../tests/support/photo.jpg`);
// note = await shim.attachFileToNote(note, `${supportDir}/photo.jpg`);
// const resource = (await Resource.all())[0];
// const noteIds = await NoteResource.associatedNoteIds(resource.id);

View File

@@ -1,18 +1,13 @@
/* eslint-disable no-unused-vars */
/* eslint-disable no-unused-vars, @typescript-eslint/no-unused-vars, prefer-const */
const time = require('@joplin/lib/time').default;
const { fileContentEqual, setupDatabase, revisionService, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const Folder = require('@joplin/lib/models/Folder').default;
const Setting = require('@joplin/lib/models/Setting').default;
const Note = require('@joplin/lib/models/Note').default;
const NoteTag = require('@joplin/lib/models/NoteTag').default;
const ItemChange = require('@joplin/lib/models/ItemChange').default;
const Tag = require('@joplin/lib/models/Tag').default;
const Revision = require('@joplin/lib/models/Revision').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
const RevisionService = require('@joplin/lib/services/RevisionService').default;
const shim = require('@joplin/lib/shim').default;
const time = require('../time').default;
const { revisionService, setupDatabaseAndSynchronizer, switchClient } = require('../testing/test-utils.js');
const Setting = require('../models/Setting').default;
const Note = require('../models/Note').default;
const ItemChange = require('../models/ItemChange').default;
const Revision = require('../models/Revision').default;
const BaseModel = require('../BaseModel').default;
const RevisionService = require('../services/RevisionService').default;
describe('services_Revision', function() {

View File

@@ -1,14 +1,14 @@
import InteropService from '@joplin/lib/services/interop/InteropService';
import { CustomExportContext, CustomImportContext, Module, ModuleType } from '@joplin/lib/services/interop/types';
import shim from '@joplin/lib/shim';
import InteropService from '../../services/interop/InteropService';
import { CustomExportContext, CustomImportContext, Module, ModuleType } from '../../services/interop/types';
import shim from '../../shim';
const { fileContentEqual, setupDatabaseAndSynchronizer, switchClient, checkThrowAsync, exportDir } = require('./test-utils.js');
import Folder from '@joplin/lib/models/Folder';
import Note from '@joplin/lib/models/Note';
import Tag from '@joplin/lib/models/Tag';
import Resource from '@joplin/lib/models/Resource';
const { fileContentEqual, setupDatabaseAndSynchronizer, switchClient, checkThrowAsync, exportDir, supportDir } = require('../../testing/test-utils.js');
import Folder from '../../models/Folder';
import Note from '../../models/Note';
import Tag from '../../models/Tag';
import Resource from '../../models/Resource';
const fs = require('fs-extra');
const ArrayUtils = require('@joplin/lib/ArrayUtils');
const ArrayUtils = require('../../ArrayUtils');
async function recreateExportDir() {
const dir = exportDir();
@@ -209,7 +209,7 @@ describe('services_InteropService', function() {
const filePath = `${exportDir()}/test.jex`;
const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
note1 = await Note.load(note1.id);
let resourceIds = await Note.linkedResourceIds(note1.body);
const resource1 = await Resource.load(resourceIds[0]);
@@ -499,7 +499,7 @@ describe('services_InteropService', function() {
const folder1 = await Folder.save({ title: 'folder1' });
const note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
await Note.save({ title: 'note2', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
const filePath = `${exportDir()}/example.test`;

View File

@@ -1,11 +1,11 @@
import InteropService from '@joplin/lib/services/interop/InteropService';
import { PluginStates } from '@joplin/lib/services/plugins/reducer';
import { setupDatabaseAndSynchronizer, switchClient, exportDir } from './test-utils';
import Folder from '@joplin/lib/models/Folder';
import Note from '@joplin/lib/models/Note';
import InteropService from '../../services/interop/InteropService';
import { PluginStates } from '../../services/plugins/reducer';
import { setupDatabaseAndSynchronizer, switchClient, exportDir } from '../../testing/test-utils';
import Folder from '../../models/Folder';
import Note from '../../models/Note';
import * as fs from 'fs-extra';
import { tempFilePath } from './test-utils';
import { ContentScriptType } from '@joplin/lib/services/plugins/api/types';
import { tempFilePath } from '../../testing/test-utils';
import { ContentScriptType } from '../../services/plugins/api/types';
async function recreateExportDir() {
const dir = exportDir();

View File

@@ -2,13 +2,13 @@
const fs = require('fs-extra');
const { setupDatabaseAndSynchronizer, switchClient, exportDir } = require('./test-utils.js');
const InteropService_Exporter_Md = require('@joplin/lib/services/interop/InteropService_Exporter_Md').default;
const BaseModel = require('@joplin/lib/BaseModel').default;
const Folder = require('@joplin/lib/models/Folder').default;
const Resource = require('@joplin/lib/models/Resource').default;
const Note = require('@joplin/lib/models/Note').default;
const shim = require('@joplin/lib/shim').default;
const { setupDatabaseAndSynchronizer, switchClient, exportDir, supportDir } = require('../../testing/test-utils.js');
const InteropService_Exporter_Md = require('../../services/interop/InteropService_Exporter_Md').default;
const BaseModel = require('../../BaseModel').default;
const Folder = require('../../models/Folder').default;
const Resource = require('../../models/Resource').default;
const Note = require('../../models/Note').default;
const shim = require('../../shim').default;
describe('services_InteropService_Exporter_Md', function() {
@@ -43,7 +43,7 @@ describe('services_InteropService_Exporter_Md', function() {
const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
const note2 = await Note.save({ title: 'note2', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
note1 = await Note.load(note1.id);
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
queueExportItem(BaseModel.TYPE_NOTE, note1);
@@ -52,7 +52,7 @@ describe('services_InteropService_Exporter_Md', function() {
const folder2 = await Folder.save({ title: 'folder2' });
let note3 = await Note.save({ title: 'note3', parent_id: folder2.id });
await shim.attachFileToNote(note3, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note3, `${supportDir}/photo.jpg`);
note3 = await Note.load(note3.id);
queueExportItem(BaseModel.TYPE_FOLDER, folder2.id);
queueExportItem(BaseModel.TYPE_NOTE, note3);
@@ -138,7 +138,7 @@ describe('services_InteropService_Exporter_Md', function() {
const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
note1 = await Note.load(note1.id);
queueExportItem(BaseModel.TYPE_FOLDER, folder1.id);
queueExportItem(BaseModel.TYPE_NOTE, note1);
@@ -147,7 +147,7 @@ describe('services_InteropService_Exporter_Md', function() {
const folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
let note2 = await Note.save({ title: 'note2', parent_id: folder2.id });
await shim.attachFileToNote(note2, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note2, `${supportDir}/photo.jpg`);
note2 = await Note.load(note2.id);
queueExportItem(BaseModel.TYPE_FOLDER, folder2.id);
queueExportItem(BaseModel.TYPE_NOTE, note2);
@@ -243,14 +243,14 @@ describe('services_InteropService_Exporter_Md', function() {
const folder1 = await Folder.save({ title: 'folder1' });
let note1 = await Note.save({ title: 'note1', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
note1 = await Note.load(note1.id);
queueExportItem(BaseModel.TYPE_NOTE, note1);
const resource1 = await Resource.load((await Note.linkedResourceIds(note1.body))[0]);
const folder2 = await Folder.save({ title: 'folder2', parent_id: folder1.id });
let note2 = await Note.save({ title: 'note2', parent_id: folder2.id });
await shim.attachFileToNote(note2, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note2, `${supportDir}/photo.jpg`);
note2 = await Note.load(note2.id);
queueExportItem(BaseModel.TYPE_NOTE, note2);
const resource2 = await Resource.load((await Note.linkedResourceIds(note2.body))[0]);

View File

@@ -48,10 +48,8 @@ export interface Command {
* Currently the supported context variables aren't documented, but you can
* find the list below:
*
* - [Global When
* Clauses](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts).
* - [Desktop app When
* Clauses](https://github.com/laurent22/joplin/blob/dev/packages/app-desktop/services/commands/stateToWhenClauseContext.ts).
* - [Global When Clauses](https://github.com/laurent22/joplin/blob/dev/packages/lib/services/commands/stateToWhenClauseContext.ts)
* - [Desktop app When Clauses](https://github.com/laurent22/joplin/blob/dev/packages/app-desktop/services/commands/stateToWhenClauseContext.ts)
*
* Note: Commands are enabled by default unless you use this property.
*/

View File

@@ -1,15 +1,15 @@
import { PaginationOrderDir } from '@joplin/lib/models/utils/types';
import Api, { RequestMethod } from '@joplin/lib/services/rest/Api';
import shim from '@joplin/lib/shim';
import { PaginationOrderDir } from '../../models/utils/types';
import Api, { RequestMethod } from '../../services/rest/Api';
import shim from '../../shim';
const { setupDatabaseAndSynchronizer, switchClient, checkThrowAsync, db, msleep } = require('./test-utils.js');
import Folder from '@joplin/lib/models/Folder';
import Resource from '@joplin/lib/models/Resource';
import Note from '@joplin/lib/models/Note';
import Tag from '@joplin/lib/models/Tag';
import NoteTag from '@joplin/lib/models/NoteTag';
import ResourceService from '@joplin/lib/services/ResourceService';
import SearchEngine from '@joplin/lib/services/searchengine/SearchEngine';
const { setupDatabaseAndSynchronizer, switchClient, checkThrowAsync, db, msleep, supportDir } = require('../../testing/test-utils.js');
import Folder from '../../models/Folder';
import Resource from '../../models/Resource';
import Note from '../../models/Note';
import Tag from '../../models/Tag';
import NoteTag from '../../models/NoteTag';
import ResourceService from '../../services/ResourceService';
import SearchEngine from '../../services/searchengine/SearchEngine';
const createFolderForPagination = async (num: number, time: number) => {
await Folder.save({
@@ -327,7 +327,7 @@ describe('services_rest_Api', function() {
}));
it('should not compress images uploaded through resource api', (async () => {
const originalImagePath = `${__dirname}/../tests/support/photo-large.png`;
const originalImagePath = `${supportDir}/photo-large.png`;
await api.route(RequestMethod.POST, 'resources', null, JSON.stringify({
title: 'testing resource',
}), [
@@ -764,7 +764,7 @@ describe('services_rest_Api', function() {
it('should return the notes associated with a resource', (async () => {
const note = await Note.save({});
await shim.attachFileToNote(note, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note, `${supportDir}/photo.jpg`);
const resource = (await Resource.all())[0];
const resourceService = new ResourceService();
@@ -778,7 +778,7 @@ describe('services_rest_Api', function() {
it('should return the resources associated with a note', (async () => {
const note = await Note.save({});
await shim.attachFileToNote(note, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note, `${supportDir}/photo.jpg`);
const resource = (await Resource.all())[0];
const r = await api.route(RequestMethod.GET, `notes/${note.id}/resources`);

View File

@@ -1,13 +1,10 @@
/* eslint-disable no-unused-vars */
/* eslint prefer-const: 0*/
/* eslint-disable no-unused-vars, @typescript-eslint/no-unused-vars, prefer-const */
const time = require('@joplin/lib/time').default;
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync, restoreDate } = require('./test-utils.js');
const SearchEngine = require('@joplin/lib/services/searchengine/SearchEngine').default;
const Note = require('@joplin/lib/models/Note').default;
const ItemChange = require('@joplin/lib/models/ItemChange').default;
const Setting = require('@joplin/lib/models/Setting').default;
const { setupDatabaseAndSynchronizer, db, sleep, switchClient } = require('../../testing/test-utils.js');
const SearchEngine = require('../../services/searchengine/SearchEngine').default;
const Note = require('../../models/Note').default;
const ItemChange = require('../../models/ItemChange').default;
const Setting = require('../../models/Setting').default;
let engine = null;

View File

@@ -1,8 +1,8 @@
import { setupDatabaseAndSynchronizer, db, switchClient } from './test-utils.js';
import SearchEngine from '@joplin/lib/services/searchengine/SearchEngine';
import SearchEngineUtils from '@joplin/lib/services/searchengine/SearchEngineUtils';
import Setting from '@joplin/lib/models/Setting';
const Note = require('@joplin/lib/models/Note').default;
import { setupDatabaseAndSynchronizer, db, switchClient } from '../../testing/test-utils.js';
import SearchEngine from '../../services/searchengine/SearchEngine';
import SearchEngineUtils from '../../services/searchengine/SearchEngineUtils';
import Setting from '../../models/Setting';
const Note = require('../../models/Note').default;
let searchEngine: any = null;

View File

@@ -1,18 +1,13 @@
/* eslint-disable no-unused-vars */
/* eslint prefer-const: 0*/
/* eslint-disable no-unused-vars, @typescript-eslint/no-unused-vars, prefer-const */
const time = require('@joplin/lib/time').default;
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, createNTestNotes, switchClient, createNTestFolders } = require('./test-utils.js');
const SearchEngine = require('@joplin/lib/services/searchengine/SearchEngine').default;
const Note = require('@joplin/lib/models/Note').default;
const Folder = require('@joplin/lib/models/Folder').default;
const Tag = require('@joplin/lib/models/Tag').default;
const ItemChange = require('@joplin/lib/models/ItemChange').default;
const Setting = require('@joplin/lib/models/Setting').default;
const Resource = require('@joplin/lib/models/Resource').default;
const shim = require('@joplin/lib/shim').default;
const ResourceService = require('@joplin/lib/services/ResourceService').default;
const time = require('../../time').default;
const { setupDatabaseAndSynchronizer, supportDir, db, createNTestNotes, switchClient } = require('../../testing/test-utils.js');
const SearchEngine = require('../../services/searchengine/SearchEngine').default;
const Note = require('../../models/Note').default;
const Folder = require('../../models/Folder').default;
const Tag = require('../../models/Tag').default;
const shim = require('../../shim').default;
const ResourceService = require('../../services/ResourceService').default;
let engine = null;
@@ -697,10 +692,10 @@ describe('services_SearchFilter', function() {
await engine.syncTables();
// let note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
n1 = await shim.attachFileToNote(n1, `${__dirname}/../tests/support/photo.jpg`);
n1 = await shim.attachFileToNote(n1, `${supportDir}/photo.jpg`);
// const resource1 = (await Resource.all())[0];
n4 = await shim.attachFileToNote(n4, `${__dirname}/../tests/support/welcome.pdf`);
n4 = await shim.attachFileToNote(n4, `${supportDir}/welcome.pdf`);
await service.indexNoteResources();
@@ -803,13 +798,13 @@ describe('services_SearchFilter', function() {
it('should support negating notebooks', (async () => {
const folder1 = await Folder.save({ title: 'folder1' });
let n1 = await Note.save({ title: 'task1', body: 'foo', parent_id: folder1.id });
let n2 = await Note.save({ title: 'task2', body: 'bar', parent_id: folder1.id });
const n1 = await Note.save({ title: 'task1', body: 'foo', parent_id: folder1.id });
const n2 = await Note.save({ title: 'task2', body: 'bar', parent_id: folder1.id });
const folder2 = await Folder.save({ title: 'folder2' });
let n3 = await Note.save({ title: 'task3', body: 'baz', parent_id: folder2.id });
let n4 = await Note.save({ title: 'task4', body: 'blah', parent_id: folder2.id });
const n3 = await Note.save({ title: 'task3', body: 'baz', parent_id: folder2.id });
const n4 = await Note.save({ title: 'task4', body: 'blah', parent_id: folder2.id });
await engine.syncTables();
@@ -830,18 +825,18 @@ describe('services_SearchFilter', function() {
it('should support both inclusion and exclusion of notebooks together', (async () => {
const parentFolder = await Folder.save({ title: 'parent' });
let n1 = await Note.save({ title: 'task1', body: 'foo', parent_id: parentFolder.id });
let n2 = await Note.save({ title: 'task2', body: 'bar', parent_id: parentFolder.id });
const n1 = await Note.save({ title: 'task1', body: 'foo', parent_id: parentFolder.id });
const n2 = await Note.save({ title: 'task2', body: 'bar', parent_id: parentFolder.id });
const subFolder = await Folder.save({ title: 'child', parent_id: parentFolder.id });
let n3 = await Note.save({ title: 'task3', body: 'baz', parent_id: subFolder.id });
let n4 = await Note.save({ title: 'task4', body: 'blah', parent_id: subFolder.id });
const n3 = await Note.save({ title: 'task3', body: 'baz', parent_id: subFolder.id });
const n4 = await Note.save({ title: 'task4', body: 'blah', parent_id: subFolder.id });
await engine.syncTables();
let rows = await engine.search('notebook:parent -notebook:child');
const rows = await engine.search('notebook:parent -notebook:child');
expect(rows.length).toBe(2);
expect(ids(rows)).toContain(n1.id);
expect(ids(rows)).toContain(n2.id);

View File

@@ -1,7 +1,7 @@
/* eslint-disable no-unused-vars */
const filterParser = require('@joplin/lib/services/searchengine/filterParser.js').default;
// import filterParser from '@joplin/lib/services/searchengine/filterParser.js';
const filterParser = require('../../services/searchengine/filterParser.js').default;
// import filterParser from '../../services/searchengine/filterParser.js';
const makeTerm = (name, value, negated, quoted = false, wildcard = false) => {
if (name === 'text') { return { name, value, negated, quoted, wildcard }; }

View File

@@ -1,11 +1,11 @@
import Setting from '@joplin/lib/models/Setting';
import { allNotesFolders, remoteNotesAndFolders, localNotesFoldersSameAsRemote } from './test-utils-synchronizer';
import Setting from '../../models/Setting';
import { allNotesFolders, remoteNotesAndFolders, localNotesFoldersSameAsRemote } from '../../testing/test-utils-synchronizer';
const { syncTargetName, afterAllCleanUp, synchronizerStart, setupDatabaseAndSynchronizer, synchronizer, sleep, switchClient, syncTargetId, fileApi } = require('./test-utils.js');
import Folder from '@joplin/lib/models/Folder';
import Note from '@joplin/lib/models/Note';
import BaseItem from '@joplin/lib/models/BaseItem';
const WelcomeUtils = require('@joplin/lib/WelcomeUtils');
const { syncTargetName, afterAllCleanUp, synchronizerStart, setupDatabaseAndSynchronizer, synchronizer, sleep, switchClient, syncTargetId, fileApi } = require('../../testing/test-utils.js');
import Folder from '../../models/Folder';
import Note from '../../models/Note';
import BaseItem from '../../models/BaseItem';
const WelcomeUtils = require('../../WelcomeUtils');
describe('Synchronizer.basics', function() {

View File

@@ -1,11 +1,11 @@
import time from '@joplin/lib/time';
import Setting from '@joplin/lib/models/Setting';
import { allNotesFolders, localNotesFoldersSameAsRemote } from './test-utils-synchronizer';
import time from '../../time';
import Setting from '../../models/Setting';
import { allNotesFolders, localNotesFoldersSameAsRemote } from '../../testing/test-utils-synchronizer';
const { synchronizerStart, setupDatabaseAndSynchronizer, sleep, switchClient, syncTargetId, loadEncryptionMasterKey, decryptionWorker } = require('./test-utils.js');
import Folder from '@joplin/lib/models/Folder';
import Note from '@joplin/lib/models/Note';
import BaseItem from '@joplin/lib/models/BaseItem';
const { synchronizerStart, setupDatabaseAndSynchronizer, sleep, switchClient, syncTargetId, loadEncryptionMasterKey, decryptionWorker } = require('../../testing/test-utils.js');
import Folder from '../../models/Folder';
import Note from '../../models/Note';
import BaseItem from '../../models/BaseItem';
describe('Synchronizer.conflicts', function() {

View File

@@ -1,15 +1,15 @@
import time from '@joplin/lib/time';
import shim from '@joplin/lib/shim';
import Setting from '@joplin/lib/models/Setting';
import time from '../../time';
import shim from '../../shim';
import Setting from '../../models/Setting';
const { synchronizerStart, allSyncTargetItemsEncrypted, kvStore, setupDatabaseAndSynchronizer, synchronizer, fileApi, switchClient, encryptionService, loadEncryptionMasterKey, decryptionWorker, checkThrowAsync } = require('./test-utils.js');
import Folder from '@joplin/lib/models/Folder';
import Note from '@joplin/lib/models/Note';
import Resource from '@joplin/lib/models/Resource';
import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
import MasterKey from '@joplin/lib/models/MasterKey';
import BaseItem from '@joplin/lib/models/BaseItem';
import { createFolderTree } from './test-utils';
const { synchronizerStart, allSyncTargetItemsEncrypted, kvStore, supportDir, setupDatabaseAndSynchronizer, synchronizer, fileApi, switchClient, encryptionService, loadEncryptionMasterKey, decryptionWorker, checkThrowAsync } = require('../../testing/test-utils.js');
import Folder from '../../models/Folder';
import Note from '../../models/Note';
import Resource from '../../models/Resource';
import ResourceFetcher from '../../services/ResourceFetcher';
import MasterKey from '../../models/MasterKey';
import BaseItem from '../../models/BaseItem';
import { createFolderTree } from '../../testing/test-utils';
let insideBeforeEach = false;
@@ -213,7 +213,7 @@ describe('Synchronizer.e2ee', function() {
const folder1 = await Folder.save({ title: 'folder1' });
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
const resource1 = (await Resource.all())[0];
await Resource.setFileSizeOnly(resource1.id, -1);
Resource.fullPath(resource1);
@@ -239,7 +239,7 @@ describe('Synchronizer.e2ee', function() {
const folder1 = await Folder.save({ title: 'folder1' });
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
await synchronizerStart();
expect(await allSyncTargetItemsEncrypted()).toBe(false);
@@ -258,7 +258,7 @@ describe('Synchronizer.e2ee', function() {
const folder1 = await Folder.save({ title: 'folder1' });
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
const masterKey = await loadEncryptionMasterKey();
await encryptionService().enableEncryption(masterKey, '123456');
await encryptionService().loadMasterKeysFromSettings();
@@ -270,7 +270,7 @@ describe('Synchronizer.e2ee', function() {
it('should decrypt the resource metadata, but not try to decrypt the file, if it is not present', (async () => {
const note1 = await Note.save({ title: 'note' });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
const masterKey = await loadEncryptionMasterKey();
await encryptionService().enableEncryption(masterKey, '123456');
await encryptionService().loadMasterKeysFromSettings();

View File

@@ -1,15 +1,15 @@
import time from '@joplin/lib/time';
import shim from '@joplin/lib/shim';
import Setting from '@joplin/lib/models/Setting';
import { NoteEntity } from '@joplin/lib/services/database/types';
import { remoteNotesFoldersResources, remoteResources } from './test-utils-synchronizer';
import time from '../../time';
import shim from '../../shim';
import Setting from '../../models/Setting';
import { NoteEntity } from '../../services/database/types';
import { remoteNotesFoldersResources, remoteResources } from '../../testing/test-utils-synchronizer';
const { synchronizerStart, tempFilePath, resourceFetcher, setupDatabaseAndSynchronizer, synchronizer, fileApi, switchClient, syncTargetId, encryptionService, loadEncryptionMasterKey, fileContentEqual, checkThrowAsync } = require('./test-utils.js');
import Folder from '@joplin/lib/models/Folder';
import Note from '@joplin/lib/models/Note';
import Resource from '@joplin/lib/models/Resource';
import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
import BaseItem from '@joplin/lib/models/BaseItem';
const { synchronizerStart, tempFilePath, resourceFetcher, supportDir, setupDatabaseAndSynchronizer, synchronizer, fileApi, switchClient, syncTargetId, encryptionService, loadEncryptionMasterKey, fileContentEqual, checkThrowAsync } = require('../../testing/test-utils.js');
import Folder from '../../models/Folder';
import Note from '../../models/Note';
import Resource from '../../models/Resource';
import ResourceFetcher from '../../services/ResourceFetcher';
import BaseItem from '../../models/BaseItem';
let insideBeforeEach = false;
@@ -31,7 +31,7 @@ describe('Synchronizer.resources', function() {
const folder1 = await Folder.save({ title: 'folder1' });
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
const resource1 = (await Resource.all())[0];
const resourcePath1 = Resource.fullPath(resource1);
await synchronizerStart();
@@ -64,7 +64,7 @@ describe('Synchronizer.resources', function() {
const folder1 = await Folder.save({ title: 'folder1' });
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
let resource1 = (await Resource.all())[0];
await synchronizerStart();
@@ -92,7 +92,7 @@ describe('Synchronizer.resources', function() {
const folder1 = await Folder.save({ title: 'folder1' });
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
await synchronizerStart();
await switchClient(2);
@@ -115,7 +115,7 @@ describe('Synchronizer.resources', function() {
const folder1 = await Folder.save({ title: 'folder1' });
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
const resource1 = (await Resource.all())[0];
const resourcePath1 = Resource.fullPath(resource1);
await synchronizerStart();
@@ -148,7 +148,7 @@ describe('Synchronizer.resources', function() {
const folder1 = await Folder.save({ title: 'folder1' });
const note1 = await Note.save({ title: 'ma note', parent_id: folder1.id });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
const resource1 = (await Resource.all())[0];
const resourcePath1 = Resource.fullPath(resource1);
await synchronizerStart();
@@ -323,7 +323,7 @@ describe('Synchronizer.resources', function() {
// does get uploaded.
const note1 = await Note.save({ title: 'note' });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
const resource = (await Resource.all())[0];
await Resource.setLocalState(resource.id, { fetch_status: Resource.FETCH_STATUS_IDLE });
await synchronizerStart();
@@ -338,7 +338,7 @@ describe('Synchronizer.resources', function() {
it('should not download resources over the limit', (async () => {
const note1 = await Note.save({ title: 'note' });
await shim.attachFileToNote(note1, `${__dirname}/../tests/support/photo.jpg`);
await shim.attachFileToNote(note1, `${supportDir}/photo.jpg`);
await synchronizer().start();
await switchClient(2);

View File

@@ -1,9 +1,9 @@
import Setting from '@joplin/lib/models/Setting';
import BaseModel from '@joplin/lib/BaseModel';
import Setting from '../../models/Setting';
import BaseModel from '../../BaseModel';
const { synchronizerStart, revisionService, setupDatabaseAndSynchronizer, synchronizer, switchClient, encryptionService, loadEncryptionMasterKey, decryptionWorker } = require('./test-utils.js');
import Note from '@joplin/lib/models/Note';
import Revision from '@joplin/lib/models/Revision';
const { synchronizerStart, revisionService, setupDatabaseAndSynchronizer, synchronizer, switchClient, encryptionService, loadEncryptionMasterKey, decryptionWorker } = require('../../testing/test-utils.js');
import Note from '../../models/Note';
import Revision from '../../models/Revision';
describe('Synchronizer.revisions', function() {

View File

@@ -6,12 +6,12 @@ describe('Synchronizer.sharing', function() {
});
// import { afterAllCleanUp, synchronizerStart, setupDatabaseAndSynchronizer, switchClient, joplinServerApi } from './test-utils';
// import Note from '@joplin/lib/models/Note';
// import BaseItem from '@joplin/lib/models/BaseItem';
// import shim from '@joplin/lib/shim';
// import Resource from '@joplin/lib/models/Resource';
// import Folder from '@joplin/lib/models/Folder';
// import { afterAllCleanUp, synchronizerStart, setupDatabaseAndSynchronizer, switchClient, joplinServerApi } from '../../testing/test-utils';
// import Note from '../../models/Note';
// import BaseItem from '../../models/BaseItem';
// import shim from '../../shim';
// import Resource from '../../models/Resource';
// import Folder from '../../models/Folder';
// describe('Synchronizer.sharing', function() {

View File

@@ -1,10 +1,10 @@
import Setting from '@joplin/lib/models/Setting';
import Setting from '../../models/Setting';
const { synchronizerStart, setupDatabaseAndSynchronizer, switchClient, encryptionService, loadEncryptionMasterKey } = require('./test-utils.js');
import Folder from '@joplin/lib/models/Folder';
import Note from '@joplin/lib/models/Note';
import Tag from '@joplin/lib/models/Tag';
import MasterKey from '@joplin/lib/models/MasterKey';
const { synchronizerStart, setupDatabaseAndSynchronizer, switchClient, encryptionService, loadEncryptionMasterKey } = require('../../testing/test-utils.js');
import Folder from '../../models/Folder';
import Note from '../../models/Note';
import Tag from '../../models/Tag';
import MasterKey from '../../models/MasterKey';
describe('Synchronizer.tags', function() {

View File

@@ -1,8 +1,8 @@
import { allNotesFolders, remoteNotesAndFolders } from './test-utils-synchronizer';
import { afterAllCleanUp, synchronizerStart, setupDatabaseAndSynchronizer, switchClient, fileApi, db } from './test-utils';
import Folder from '@joplin/lib/models/Folder';
import Note from '@joplin/lib/models/Note';
import { clearLocalDataForRedownload, clearLocalSyncStateForReupload } from '@joplin/lib/services/synchronizer/tools';
import { allNotesFolders, remoteNotesAndFolders } from '../../testing/test-utils-synchronizer';
import { afterAllCleanUp, synchronizerStart, setupDatabaseAndSynchronizer, switchClient, fileApi, db } from '../../testing/test-utils';
import Folder from '../../models/Folder';
import Note from '../../models/Note';
import { clearLocalDataForRedownload, clearLocalSyncStateForReupload } from '../../services/synchronizer/tools';
describe('Synchronizer.tools', function() {

View File

@@ -1,7 +1,7 @@
import LockHandler, { LockType, LockHandlerOptions, Lock } from '@joplin/lib/services/synchronizer/LockHandler';
import LockHandler, { LockType, LockHandlerOptions, Lock } from '../../services/synchronizer/LockHandler';
const { isNetworkSyncTarget, fileApi, setupDatabaseAndSynchronizer, synchronizer, switchClient, msleep, expectThrow, expectNotThrow } = require('./test-utils.js');
const { isNetworkSyncTarget, fileApi, setupDatabaseAndSynchronizer, synchronizer, switchClient, msleep, expectThrow, expectNotThrow } = require('../../testing/test-utils.js');
// For tests with memory of file system we can use low intervals to make the tests faster.
// However if we use such low values with network sync targets, some calls might randomly fail with

View File

@@ -1,6 +1,6 @@
import LockHandler from '@joplin/lib/services/synchronizer/LockHandler';
import MigrationHandler from '@joplin/lib/services/synchronizer/MigrationHandler';
import { Dirnames } from '@joplin/lib/services/synchronizer/utils/types';
import LockHandler from '../../services/synchronizer/LockHandler';
import MigrationHandler from '../../services/synchronizer/MigrationHandler';
import { Dirnames } from '../../services/synchronizer/utils/types';
// To create a sync target snapshot for the current syncVersion:
// - In test-utils, set syncTargetName_ to "filesystem"
@@ -8,10 +8,10 @@ import { Dirnames } from '@joplin/lib/services/synchronizer/utils/types';
// gulp buildTests -L && node tests-build/support/createSyncTargetSnapshot.js normal && node tests-build/support/createSyncTargetSnapshot.js e2ee
const { setSyncTargetName, fileApi, synchronizer, decryptionWorker, encryptionService, setupDatabaseAndSynchronizer, switchClient, expectThrow, expectNotThrow } = require('./test-utils.js');
const { deploySyncTargetSnapshot, testData, checkTestData } = require('./support/syncTargetUtils');
import Setting from '@joplin/lib/models/Setting';
import MasterKey from '@joplin/lib/models/MasterKey';
const { setSyncTargetName, fileApi, synchronizer, decryptionWorker, encryptionService, setupDatabaseAndSynchronizer, switchClient, expectThrow, expectNotThrow } = require('../../testing/test-utils.js');
const { deploySyncTargetSnapshot, testData, checkTestData } = require('../../testing/syncTargetUtils');
import Setting from '../../models/Setting';
import MasterKey from '../../models/MasterKey';
const specTimeout = 60000 * 10; // Nextcloud tests can be slow

View File

@@ -1,14 +1,14 @@
const { syncDir, fileApi, synchronizer, createSyncTargetSnapshot, loadEncryptionMasterKey, decryptionWorker, encryptionService, setupDatabaseAndSynchronizer, switchClient, expectThrow, expectNotThrow } = require('../test-utils.js');
const Setting = require('@joplin/lib/models/Setting').default;
const Folder = require('@joplin/lib/models/Folder').default;
const Note = require('@joplin/lib/models/Note').default;
const Tag = require('@joplin/lib/models/Tag').default;
const Resource = require('@joplin/lib/models/Resource').default;
const markdownUtils = require('@joplin/lib/markdownUtils').default;;
const shim = require('@joplin/lib/shim').default;
const { syncDir, synchronizer, supportDir, loadEncryptionMasterKey, setupDatabaseAndSynchronizer, switchClient } = require('../testing/test-utils.js');
const Setting = require('../models/Setting').default;
const Folder = require('../models/Folder').default;
const Note = require('../models/Note').default;
const Tag = require('../models/Tag').default;
const Resource = require('../models/Resource').default;
const markdownUtils = require('../markdownUtils').default;
const shim = require('../shim').default;
const fs = require('fs-extra');
const snapshotBaseDir = `${__dirname}/../../tests/support/syncTargetSnapshots`;
const snapshotBaseDir = `${supportDir}/syncTargetSnapshots`;
const testData = {
folder1: {
@@ -45,7 +45,7 @@ async function createTestData(data) {
} else {
const note = await Note.save({ title: n, parent_id: parentId });
if (s[n].resource) {
await shim.attachFileToNote(note, `${__dirname}/../../tests/support/photo.jpg`);
await shim.attachFileToNote(note, `${supportDir}/photo.jpg`);
}
if (s[n].tags) {
@@ -106,7 +106,7 @@ async function deploySyncTargetSnapshot(syncTargetType, syncVersion) {
async function main(syncTargetType) {
const validSyncTargetTypes = ['normal', 'e2ee'];
if (!validSyncTargetTypes.includes(syncTargetType)) throw new Error('Sync target type must be: ' + validSyncTargetTypes.join(', '));
if (!validSyncTargetTypes.includes(syncTargetType)) throw new Error(`Sync target type must be: ${validSyncTargetTypes.join(', ')}`);
await setupDatabaseAndSynchronizer(1);
await switchClient(1);
@@ -126,7 +126,7 @@ async function main(syncTargetType) {
await fs.mkdirp(destDir);
await fs.copy(syncDir, destDir);
console.info('Sync target snapshot created in: ' + destDir);
console.info(`Sync target snapshot created in: ${destDir}`);
}
module.exports = {
@@ -134,4 +134,4 @@ module.exports = {
main,
testData,
deploySyncTargetSnapshot,
};
};

View File

@@ -1,9 +1,8 @@
import BaseModel from '@joplin/lib/BaseModel';
const { fileApi } = require('./test-utils.js');
import Folder from '@joplin/lib/models/Folder';
import Note from '@joplin/lib/models/Note';
import BaseItem from '@joplin/lib/models/BaseItem';
import BaseModel from '../BaseModel';
const { fileApi } = require('../testing/../testing/test-utils.js');
import Folder from '../models/Folder';
import Note from '../models/Note';
import BaseItem from '../models/BaseItem';
export async function allNotesFolders() {
const folders = await Folder.all();

View File

@@ -1,65 +1,62 @@
/* eslint-disable require-atomic-updates */
import BaseApplication from '@joplin/lib/BaseApplication';
import BaseModel from '@joplin/lib/BaseModel';
import Logger, { TargetType, LoggerWrapper, LogLevel } from '@joplin/lib/Logger';
import Setting from '@joplin/lib/models/Setting';
import BaseService from '@joplin/lib/services/BaseService';
import FsDriverNode from '@joplin/lib/fs-driver-node';
import time from '@joplin/lib/time';
import shim from '@joplin/lib/shim';
import uuid from '@joplin/lib/uuid';
import ResourceService from '@joplin/lib/services/ResourceService';
import KeymapService from '@joplin/lib/services/KeymapService';
import KvStore from '@joplin/lib/services/KvStore';
import KeychainServiceDriver from '@joplin/lib/services/keychain/KeychainServiceDriver.node';
import KeychainServiceDriverDummy from '@joplin/lib/services/keychain/KeychainServiceDriver.dummy';
import PluginRunner from '../app/services/plugins/PluginRunner';
import PluginService from '@joplin/lib/services/plugins/PluginService';
import FileApiDriverJoplinServer from '@joplin/lib/file-api-driver-joplinServer';
import OneDriveApi from '@joplin/lib/onedrive-api';
import SyncTargetOneDrive from '@joplin/lib/SyncTargetOneDrive';
import JoplinDatabase from '@joplin/lib/JoplinDatabase';
import BaseApplication from '../BaseApplication';
import BaseModel from '../BaseModel';
import Logger, { TargetType, LoggerWrapper, LogLevel } from '../Logger';
import Setting from '../models/Setting';
import BaseService from '../services/BaseService';
import FsDriverNode from '../fs-driver-node';
import time from '../time';
import shim from '../shim';
import uuid from '../uuid';
import ResourceService from '../services/ResourceService';
import KeymapService from '../services/KeymapService';
import KvStore from '../services/KvStore';
import KeychainServiceDriver from '../services/keychain/KeychainServiceDriver.node';
import KeychainServiceDriverDummy from '../services/keychain/KeychainServiceDriver.dummy';
import PluginRunner from '../../app-cli/app/services/plugins/PluginRunner';
import PluginService from '../services/plugins/PluginService';
import FileApiDriverJoplinServer from '../file-api-driver-joplinServer';
import OneDriveApi from '../onedrive-api';
import SyncTargetOneDrive from '../SyncTargetOneDrive';
import JoplinDatabase from '../JoplinDatabase';
const fs = require('fs-extra');
const { DatabaseDriverNode } = require('@joplin/lib/database-driver-node.js');
import Folder from '@joplin/lib/models/Folder';
import Note from '@joplin/lib/models/Note';
import ItemChange from '@joplin/lib/models/ItemChange';
import Resource from '@joplin/lib/models/Resource';
import Tag from '@joplin/lib/models/Tag';
import NoteTag from '@joplin/lib/models/NoteTag';
import Revision from '@joplin/lib/models/Revision';
import MasterKey from '@joplin/lib/models/MasterKey';
import BaseItem from '@joplin/lib/models/BaseItem';
const { FileApi } = require('@joplin/lib/file-api.js');
const { FileApiDriverMemory } = require('@joplin/lib/file-api-driver-memory.js');
const { FileApiDriverLocal } = require('@joplin/lib/file-api-driver-local.js');
const { FileApiDriverWebDav } = require('@joplin/lib/file-api-driver-webdav.js');
const { FileApiDriverDropbox } = require('@joplin/lib/file-api-driver-dropbox.js');
const { FileApiDriverOneDrive } = require('@joplin/lib/file-api-driver-onedrive.js');
const { FileApiDriverAmazonS3 } = require('@joplin/lib/file-api-driver-amazon-s3.js');
const { shimInit } = require('@joplin/lib/shim-init-node.js');
const SyncTargetRegistry = require('@joplin/lib/SyncTargetRegistry.js');
const SyncTargetMemory = require('@joplin/lib/SyncTargetMemory.js');
const SyncTargetFilesystem = require('@joplin/lib/SyncTargetFilesystem.js');
const SyncTargetNextcloud = require('@joplin/lib/SyncTargetNextcloud.js');
const SyncTargetDropbox = require('@joplin/lib/SyncTargetDropbox.js');
const SyncTargetAmazonS3 = require('@joplin/lib/SyncTargetAmazonS3.js');
import SyncTargetJoplinServer from '@joplin/lib/SyncTargetJoplinServer';
import EncryptionService from '@joplin/lib/services/EncryptionService';
import DecryptionWorker from '@joplin/lib/services/DecryptionWorker';
import RevisionService from '@joplin/lib/services/RevisionService';
import ResourceFetcher from '@joplin/lib/services/ResourceFetcher';
const WebDavApi = require('@joplin/lib/WebDavApi');
const DropboxApi = require('@joplin/lib/DropboxApi');
import JoplinServerApi from '@joplin/lib/JoplinServerApi';
import { FolderEntity } from '@joplin/lib/services/database/types';
const { loadKeychainServiceAndSettings } = require('@joplin/lib/services/SettingUtils');
const { DatabaseDriverNode } = require('../database-driver-node.js');
import Folder from '../models/Folder';
import Note from '../models/Note';
import ItemChange from '../models/ItemChange';
import Resource from '../models/Resource';
import Tag from '../models/Tag';
import NoteTag from '../models/NoteTag';
import Revision from '../models/Revision';
import MasterKey from '../models/MasterKey';
import BaseItem from '../models/BaseItem';
const { FileApi } = require('../file-api.js');
const { FileApiDriverMemory } = require('../file-api-driver-memory.js');
const { FileApiDriverLocal } = require('../file-api-driver-local.js');
const { FileApiDriverWebDav } = require('../file-api-driver-webdav.js');
const { FileApiDriverDropbox } = require('../file-api-driver-dropbox.js');
const { FileApiDriverOneDrive } = require('../file-api-driver-onedrive.js');
const { FileApiDriverAmazonS3 } = require('../file-api-driver-amazon-s3.js');
const SyncTargetRegistry = require('../SyncTargetRegistry.js');
const SyncTargetMemory = require('../SyncTargetMemory.js');
const SyncTargetFilesystem = require('../SyncTargetFilesystem.js');
const SyncTargetNextcloud = require('../SyncTargetNextcloud.js');
const SyncTargetDropbox = require('../SyncTargetDropbox.js');
const SyncTargetAmazonS3 = require('../SyncTargetAmazonS3.js');
import SyncTargetJoplinServer from '../SyncTargetJoplinServer';
import EncryptionService from '../services/EncryptionService';
import DecryptionWorker from '../services/DecryptionWorker';
import RevisionService from '../services/RevisionService';
import ResourceFetcher from '../services/ResourceFetcher';
const WebDavApi = require('../WebDavApi');
const DropboxApi = require('../DropboxApi');
import JoplinServerApi from '../JoplinServerApi';
import { FolderEntity } from '../services/database/types';
import { credentialFile } from '../utils/credentialFiles';
const { loadKeychainServiceAndSettings } = require('../services/SettingUtils');
const md5 = require('md5');
const S3 = require('aws-sdk/clients/s3');
const { Dirnames } = require('@joplin/lib/services/synchronizer/utils/types');
const sharp = require('sharp');
const { credentialFile } = require('@joplin/tools/tool-utils');
const { Dirnames } = require('../services/synchronizer/utils/types');
// Each suite has its own separate data and temp directory so that multiple
// suites can be run at the same time. suiteName is what is used to
@@ -84,16 +81,6 @@ let currentClient_ = 1;
// https://stackoverflow.com/questions/9768444/possible-eventemitter-memory-leak-detected
process.setMaxListeners(0);
let keytar;
try {
keytar = shim.platformSupportsKeyChain() ? require('keytar') : null;
} catch (error) {
console.error('Cannot load keytar - keychain support will be disabled', error);
keytar = null;
}
shimInit(sharp, keytar);
shim.setIsTestingEnv(true);
const fsDriver = new FsDriverNode();
@@ -102,13 +89,17 @@ Resource.fsDriver_ = fsDriver;
EncryptionService.fsDriver_ = fsDriver;
FileApiDriverLocal.fsDriver_ = fsDriver;
const logDir = `${__dirname}/../tests/logs`;
const baseTempDir = `${__dirname}/../tests/tmp/${suiteName_}`;
const supportDir = `${__dirname}/support`;
// Most test units were historically under /app-cli so most test-related
// directories are there but that should be moved eventually under the right
// packages, or even out of the monorepo for temp files, logs, etc.
const oldTestDir = `${__dirname}/../../app-cli/tests`;
const logDir = `${oldTestDir}/logs`;
const baseTempDir = `${oldTestDir}/tmp/${suiteName_}`;
const supportDir = `${oldTestDir}/support`;
// We add a space in the data directory path as that will help uncover
// various space-in-path issues.
const dataDir = `${__dirname}/test data/${suiteName_}`;
const dataDir = `${oldTestDir}/test data/${suiteName_}`;
const profileDir = `${dataDir}/profile`;
fs.mkdirpSync(logDir, 0o755);
@@ -153,7 +144,7 @@ setSyncTargetName('memory');
// console.info(`Testing with sync target: ${syncTargetName_}`);
const syncDir = `${__dirname}/../tests/sync/${suiteName_}`;
const syncDir = `${oldTestDir}/sync/${suiteName_}`;
// 90 seconds now that the tests are running in parallel and have been
// split into smaller suites might not be necessary but for now leave it
@@ -525,7 +516,7 @@ async function initFileApi() {
} else if (syncTargetId_ == SyncTargetRegistry.nameToId('memory')) {
fileApi = new FileApi('/root', new FileApiDriverMemory());
} else if (syncTargetId_ == SyncTargetRegistry.nameToId('nextcloud')) {
const options = require(`${__dirname}/../tests/support/nextcloud-auth.json`);
const options = require(`${oldTestDir}/support/nextcloud-auth.json`);
const api = new WebDavApi({
baseUrl: () => options.baseUrl,
username: () => options.username,
@@ -537,7 +528,7 @@ async function initFileApi() {
// https://www.dropbox.com/developers/apps/
// Then select "JoplinTest" and click "Generated access token"
const api = new DropboxApi();
const authTokenPath = `${__dirname}/support/dropbox-auth.txt`;
const authTokenPath = `${oldTestDir}/support/dropbox-auth.txt`;
const authToken = fs.readFileSync(authTokenPath, 'utf8');
if (!authToken) throw new Error(`Dropbox auth token missing in ${authTokenPath}`);
api.setAuthToken(authToken);
@@ -556,7 +547,7 @@ async function initFileApi() {
mustRunInBand();
const { parameters, setEnvOverride } = require('@joplin/lib/parameters.js');
const { parameters, setEnvOverride } = require('../parameters.js');
Setting.setConstant('env', 'dev');
setEnvOverride('test');
const config = parameters().oneDriveTest;
@@ -572,7 +563,7 @@ async function initFileApi() {
const appDir = await api.appDirectory();
fileApi = new FileApi(appDir, new FileApiDriverOneDrive(api));
} else if (syncTargetId_ == SyncTargetRegistry.nameToId('amazon_s3')) {
const amazonS3CredsPath = `${__dirname}/support/amazon-s3-auth.json`;
const amazonS3CredsPath = `${oldTestDir}/support/amazon-s3-auth.json`;
const amazonS3Creds = require(amazonS3CredsPath);
if (!amazonS3Creds || !amazonS3Creds.accessKeyId) throw new Error(`AWS auth JSON missing in ${amazonS3CredsPath} format should be: { "accessKeyId": "", "secretAccessKey": "", "bucket": "mybucket"}`);
const api = new S3({ accessKeyId: amazonS3Creds.accessKeyId, secretAccessKey: amazonS3Creds.secretAccessKey, s3UseArnRegion: true });

View File

@@ -1,9 +1,4 @@
/* eslint-disable no-unused-vars */
const time = require('@joplin/lib/time').default;
const { fileContentEqual, setupDatabase, setupDatabaseAndSynchronizer, db, synchronizer, fileApi, sleep, clearDatabase, switchClient, syncTargetId, objectsEqual, checkThrowAsync } = require('./test-utils.js');
const timeUtils = require('@joplin/lib/time');
const time = require('./time').default;
describe('timeUtils', function() {

View File

@@ -1,5 +1,5 @@
const urlUtils = require('@joplin/lib/urlUtils.js');
const urlUtils = require('./urlUtils.js');
describe('urlUtils', function() {

View File

@@ -0,0 +1,35 @@
const fs = require('fs-extra');
export async function credentialDir() {
const username = require('os').userInfo().username;
const toTry = [
`c:/Users/${username}/joplin-credentials`,
`/mnt/c/Users/${username}/joplin-credentials`,
`/home/${username}/joplin-credentials`,
`/Users/${username}/joplin-credentials`,
];
for (const dirPath of toTry) {
if (await fs.pathExists(dirPath)) return dirPath;
}
throw new Error(`Could not find credential directory in any of these paths: ${JSON.stringify(toTry)}`);
}
export async function credentialFile(filename: string) {
const rootDir = await credentialDir();
const output = `${rootDir}/${filename}`;
if (!(await fs.pathExists(output))) throw new Error(`No such file: ${output}`);
return output;
}
export async function readCredentialFile(filename: string, defaultValue: string = '') {
try {
const filePath = await credentialFile(filename);
const r = await fs.readFile(filePath);
return r.toString();
} catch (error) {
return defaultValue;
}
}

View File

@@ -6,4 +6,5 @@ db-*.sqlite
*.pid
logs/
tests/temp/
temp/
temp/
.env

View File

@@ -1,4 +1,9 @@
{
"verbose": true,
"watch": ["dist/", "../renderer", "../lib"]
"watch": [
"dist/",
"../renderer",
"../lib",
"src/views"
]
}

View File

@@ -1389,6 +1389,15 @@
"integrity": "sha512-9fq4jZVhPNW8r+UYKnxF1e2HkDWOWKM5bC2/7c9wPV835I0aOrVbS/Hw/pWPk2uKrNXQqg9Z959Kz+IYDd5p3w==",
"dev": true
},
"@types/nodemailer": {
"version": "6.4.1",
"resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.1.tgz",
"integrity": "sha512-8081UY/0XTTDpuGqCnDc8IY+Q3DSg604wB3dBH0CaZlj4nZWHWuxtZ3NRZ9c9WUrz1Vfm6wioAUnqL3bsh49uQ==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/normalize-package-data": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
@@ -5958,6 +5967,19 @@
"minimist": "^1.2.5"
}
},
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ=="
},
"moment-timezone": {
"version": "0.5.33",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.33.tgz",
"integrity": "sha512-PTc2vcT8K9J5/9rDEPe5czSIKgLoGsH8UNpA4qZTVw0Vd/Uz19geE9abbIOQKaAQFcnQ3v5YEXrbSc5BpshH+w==",
"requires": {
"moment": ">= 2.9.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -6045,6 +6067,14 @@
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
"dev": true
},
"node-cron": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.0.tgz",
"integrity": "sha512-DDwIvvuCwrNiaU7HEivFDULcaQualDv7KoNlB/UU1wPW0n1tDEmBJKhEIE6DlF2FuoOHcNbLJ8ITL2Iv/3AWmA==",
"requires": {
"moment-timezone": "^0.5.31"
}
},
"node-env-file": {
"version": "0.1.8",
"resolved": "https://registry.npmjs.org/node-env-file/-/node-env-file-0.1.8.tgz",
@@ -6148,6 +6178,11 @@
}
}
},
"nodemailer": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.6.0.tgz",
"integrity": "sha512-ikSMDU1nZqpo2WUPE0wTTw/NGGImTkwpJKDIFPZT+YvvR9Sj+ze5wzu95JHkBMglQLoG2ITxU21WukCC/XsFkg=="
},
"nodemon": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.6.tgz",

View File

@@ -3,7 +3,7 @@
"version": "2.0.1",
"private": true,
"scripts": {
"start-dev": "nodemon --config nodemon.json dist/app.js --env dev",
"start-dev": "nodemon --config nodemon.json --ext ts,js,mustache,css,tsx dist/app.js --env dev",
"start": "node dist/app.js",
"generateTypes": "rm -f db-buildTypes.sqlite && npm run start -- --migrate-db --env buildTypes && node dist/tools/generateTypes.js && mv db-buildTypes.sqlite schema.sqlite",
"tsc": "tsc --project tsconfig.json",
@@ -23,6 +23,7 @@
"dayjs": "^1.9.8",
"formidable": "^1.2.2",
"fs-extra": "^8.1.0",
"handlebars": "^4.7.7",
"html-entities": "^1.3.1",
"knex": "0.95.4",
"koa": "^2.8.1",
@@ -30,11 +31,13 @@
"mustache": "^3.1.0",
"nanoid": "^2.1.1",
"node-env-file": "^0.1.8",
"nodemailer": "^6.6.0",
"nodemon": "^2.0.6",
"pg": "^8.5.1",
"pretty-bytes": "^5.6.0",
"query-string": "^6.8.3",
"sqlite3": "^4.1.0",
"node-cron": "^3.0.0",
"yargs": "^14.0.0"
},
"devDependencies": {
@@ -46,6 +49,7 @@
"@types/koa": "^2.0.49",
"@types/markdown-it": "^12.0.0",
"@types/mustache": "^0.8.32",
"@types/nodemailer": "^6.4.1",
"@types/yargs": "^13.0.2",
"jest": "^26.6.3",
"jsdom": "^16.4.0",

Binary file not shown.

View File

@@ -67,11 +67,22 @@ function markPasswords(o: Record<string, any>): Record<string, any> {
return output;
}
async function main() {
if (argv.envFile) {
nodeEnvFile(argv.envFile);
async function getEnvFilePath(env: Env, argv: any): Promise<string> {
if (argv.envFile) return argv.envFile;
if (env === Env.Dev) {
const envFilePath = `${require('os').homedir()}/joplin-credentials/server.env`;
if (await fs.pathExists(envFilePath)) return envFilePath;
}
return '';
}
async function main() {
const envFilePath = await getEnvFilePath(env, argv);
if (envFilePath) nodeEnvFile(envFilePath);
if (!envVariables[env]) throw new Error(`Invalid env: ${env}`);
initConfig({
@@ -91,6 +102,8 @@ async function main() {
});
Logger.initializeGlobalLogger(globalLogger);
if (envFilePath) appLogger().info(`Env variables were loaded from: ${envFilePath}`);
const pidFile = argv.pidfile as string;
if (pidFile) {
@@ -129,7 +142,7 @@ async function main() {
const appContext = app.context as AppContext;
await setupAppContext(appContext, env, connectionCheck.connection, appLogger);
await initializeJoplinUtils(config(), appContext.models);
await initializeJoplinUtils(config(), appContext.models, appContext.services.mustache);
appLogger().info('Migrating database...');
await migrateDb(appContext.db);

View File

@@ -1,5 +1,5 @@
import { rtrimSlashes } from '@joplin/lib/path-utils';
import { Config, DatabaseConfig, DatabaseConfigClient } from './utils/types';
import { Config, DatabaseConfig, DatabaseConfigClient, MailerConfig } from './utils/types';
import * as pathUtils from 'path';
export interface EnvVariables {
@@ -14,6 +14,15 @@ export interface EnvVariables {
POSTGRES_HOST?: string;
POSTGRES_PORT?: string;
MAILER_ENABLED?: string;
MAILER_HOST?: string;
MAILER_PORT?: string;
MAILER_SECURE?: string;
MAILER_AUTH_USER?: string;
MAILER_AUTH_PASSWORD?: string;
MAILER_NOREPLY_NAME?: string;
MAILER_NOREPLY_EMAIL?: string;
SQLITE_DATABASE?: string;
}
@@ -57,6 +66,19 @@ function databaseConfigFromEnv(runningInDocker: boolean, env: EnvVariables): Dat
};
}
function mailerConfigFromEnv(env: EnvVariables): MailerConfig {
return {
enabled: env.MAILER_ENABLED !== '0',
host: env.MAILER_HOST || '',
port: Number(env.MAILER_PORT || 587),
secure: !!Number(env.MAILER_SECURE) || true,
authUser: env.MAILER_AUTH_USER || '',
authPassword: env.MAILER_AUTH_PASSWORD || '',
noReplyName: env.MAILER_NOREPLY_NAME || '',
noReplyEmail: env.MAILER_NOREPLY_EMAIL || '',
};
}
function baseUrlFromEnv(env: any, appPort: number): string {
if (env.APP_BASE_URL) {
return rtrimSlashes(env.APP_BASE_URL);
@@ -81,6 +103,7 @@ export function initConfig(env: EnvVariables, overrides: any = null) {
tempDir: `${rootDir}/temp`,
logDir: `${rootDir}/logs`,
database: databaseConfigFromEnv(runningInDocker_, env),
mailer: mailerConfigFromEnv(env),
port: appPort,
baseUrl: baseUrlFromEnv(env, appPort),
...overrides,

View File

@@ -218,6 +218,11 @@ export enum ItemType {
User,
}
export enum EmailSender {
NoReply = 1,
Support = 2,
}
export enum ChangeType {
Create = 1,
Update = 2,
@@ -277,6 +282,8 @@ export interface User extends WithDates, WithUuid {
is_admin?: number;
max_item_size?: number;
can_share?: number;
email_confirmed?: number;
must_set_password?: number;
}
export interface Session extends WithDates, WithUuid {
@@ -370,6 +377,25 @@ export interface Change extends WithDates, WithUuid {
user_id?: Uuid;
}
export interface Email extends WithDates {
id?: number;
recipient_name?: string;
recipient_email?: string;
recipient_id?: Uuid;
sender_id?: EmailSender;
subject?: string;
body?: string;
sent_time?: number;
sent_success?: number;
error?: string;
}
export interface Token extends WithDates {
id?: number;
value?: string;
user_id?: Uuid;
}
export const databaseSchema: DatabaseTables = {
users: {
id: { type: 'string' },
@@ -381,6 +407,8 @@ export const databaseSchema: DatabaseTables = {
created_time: { type: 'string' },
max_item_size: { type: 'number' },
can_share: { type: 'number' },
email_confirmed: { type: 'number' },
must_set_password: { type: 'number' },
},
sessions: {
id: { type: 'string' },
@@ -485,5 +513,26 @@ export const databaseSchema: DatabaseTables = {
previous_item: { type: 'string' },
user_id: { type: 'string' },
},
emails: {
id: { type: 'number' },
recipient_name: { type: 'string' },
recipient_email: { type: 'string' },
recipient_id: { type: 'string' },
sender_id: { type: 'number' },
subject: { type: 'string' },
body: { type: 'string' },
sent_time: { type: 'string' },
sent_success: { type: 'number' },
error: { type: 'string' },
updated_time: { type: 'string' },
created_time: { type: 'string' },
},
tokens: {
id: { type: 'number' },
value: { type: 'string' },
user_id: { type: 'string' },
updated_time: { type: 'string' },
created_time: { type: 'string' },
},
};
// AUTO-GENERATED-TYPES

View File

@@ -19,7 +19,7 @@ async function handleChangeAdminPasswordNotification(ctx: AppContext) {
ctx.owner.id,
'change_admin_password',
NotificationLevel.Important,
_('The default admin password is insecure and has not been changed! [Change it now](%s)', await ctx.models.user().profileUrl())
_('The default admin password is insecure and has not been changed! [Change it now](%s)', ctx.models.user().profileUrl())
);
} else {
await notificationModel.markAsRead(ctx.owner.id, 'change_admin_password');

View File

@@ -1,15 +1,15 @@
import { routeResponseFormat, Response, RouteResponseFormat, execRequest } from '../utils/routeUtils';
import { AppContext, Env } from '../utils/types';
import MustacheService, { isView, View } from '../services/MustacheService';
import config from '../config';
import { isView, View } from '../services/MustacheService';
// import config from '../config';
let mustache_: MustacheService = null;
function mustache(): MustacheService {
if (!mustache_) {
mustache_ = new MustacheService(config().viewDir, config().baseUrl);
}
return mustache_;
}
// let mustache_: MustacheService = null;
// function mustache(): MustacheService {
// if (!mustache_) {
// mustache_ = new MustacheService(config().viewDir, config().baseUrl);
// }
// return mustache_;
// }
export default async function(ctx: AppContext) {
ctx.appLogger().info(`${ctx.request.method} ${ctx.path}`);
@@ -21,7 +21,7 @@ export default async function(ctx: AppContext) {
ctx.response = responseObject.response;
} else if (isView(responseObject)) {
ctx.response.status = 200;
ctx.response.body = await mustache().renderView(responseObject, {
ctx.response.body = await ctx.services.mustache.renderView(responseObject, {
notifications: ctx.notifications || [],
hasNotifications: !!ctx.notifications && !!ctx.notifications.length,
owner: ctx.owner,
@@ -55,7 +55,7 @@ export default async function(ctx: AppContext) {
owner: ctx.owner,
},
};
ctx.response.body = await mustache().renderView(view);
ctx.response.body = await ctx.services.mustache.renderView(view);
} else { // JSON
ctx.response.set('Content-Type', 'application/json');
const r: any = { error: error.message };

View File

@@ -0,0 +1,47 @@
import { Knex } from 'knex';
import { DbConnection } from '../db';
export async function up(db: DbConnection): Promise<any> {
await db.schema.alterTable('users', function(table: Knex.CreateTableBuilder) {
table.integer('email_confirmed').defaultTo(0).notNullable();
table.integer('must_set_password').defaultTo(0).notNullable();
});
await db.schema.createTable('emails', function(table: Knex.CreateTableBuilder) {
table.increments('id').unique().primary().notNullable();
table.text('recipient_name', 'mediumtext').defaultTo('').notNullable();
table.text('recipient_email', 'mediumtext').defaultTo('').notNullable();
table.string('recipient_id', 32).defaultTo(0).notNullable();
table.integer('sender_id').notNullable();
table.string('subject', 128).notNullable();
table.text('body').notNullable();
table.bigInteger('sent_time').defaultTo(0).notNullable();
table.integer('sent_success').defaultTo(0).notNullable();
table.text('error').defaultTo('').notNullable();
table.bigInteger('updated_time').notNullable();
table.bigInteger('created_time').notNullable();
});
await db.schema.createTable('tokens', function(table: Knex.CreateTableBuilder) {
table.increments('id').unique().primary().notNullable();
table.string('value', 32).notNullable();
table.string('user_id', 32).defaultTo('').notNullable();
table.bigInteger('updated_time').notNullable();
table.bigInteger('created_time').notNullable();
});
await db.schema.alterTable('emails', function(table: Knex.CreateTableBuilder) {
table.index(['sent_time']);
table.index(['sent_success']);
});
await db('users').update({ email_confirmed: 1 });
await db.schema.alterTable('tokens', function(table: Knex.CreateTableBuilder) {
table.index(['value', 'user_id']);
});
}
export async function down(_db: DbConnection): Promise<any> {
}

View File

@@ -272,10 +272,10 @@ export default abstract class BaseModel<T> {
return this.db(this.tableName).select(options.fields || this.defaultFields).where({ id: id }).first();
}
public async delete(id: string | string[], options: DeleteOptions = {}): Promise<void> {
public async delete(id: string | string[] | number | number[], options: DeleteOptions = {}): Promise<void> {
if (!id) throw new Error('id cannot be empty');
const ids = typeof id === 'string' ? [id] : id;
const ids = (typeof id === 'string' || typeof id === 'number') ? [id] : id;
if (!ids.length) throw new Error('no id provided');

View File

@@ -0,0 +1,33 @@
import { Uuid, Email, EmailSender } from '../db';
import BaseModel from './BaseModel';
export interface EmailToSend {
sender_id: EmailSender;
recipient_email: string;
subject: string;
body: string;
recipient_name?: string;
recipient_id?: Uuid;
}
export default class EmailModel extends BaseModel<Email> {
public get tableName(): string {
return 'emails';
}
protected hasUuid(): boolean {
return false;
}
public async push(email: EmailToSend) {
EmailModel.eventEmitter.emit('saved');
return super.save({ ...email });
}
public async needToBeSent(): Promise<Email[]> {
return this.db(this.tableName).where('sent_time', '=', 0);
}
}

View File

@@ -0,0 +1,30 @@
import { createUserAndSession, beforeAllDb, afterAllTests, beforeEachDb, models } from '../utils/testing/testUtils';
describe('TokenModel', function() {
beforeAll(async () => {
await beforeAllDb('TokenModel');
});
afterAll(async () => {
await afterAllTests();
});
beforeEach(async () => {
await beforeEachDb();
});
test('should delete old tokens', async function() {
const { user: user1 } = await createUserAndSession(1);
await models().token().generate(user1.id);
const [token1, token2] = await models().token().all();
await models().token().save({ id: token1.id, created_time: Date.now() - 2629746000 });
await models().token().deleteExpiredTokens();
const tokens = await models().token().all();
expect(tokens.length).toBe(1);
expect(tokens[0].id).toBe(token2.id);
});
});

View File

@@ -0,0 +1,62 @@
import { Token, Uuid } from '../db';
import { ErrorForbidden } from '../utils/errors';
import uuidgen from '../utils/uuidgen';
import BaseModel from './BaseModel';
export default class TokenModel extends BaseModel<Token> {
private tokenTtl_: number = 7 * 24 * 60 * 1000;
public get tableName(): string {
return 'tokens';
}
protected hasUuid(): boolean {
return false;
}
public async generate(userId: Uuid): Promise<string> {
const token = await this.save({
value: uuidgen(32),
user_id: userId,
});
return token.value;
}
public async checkToken(userId: string, tokenValue: string): Promise<void> {
if (!(await this.isValid(userId, tokenValue))) throw new ErrorForbidden('Invalid or expired token');
}
private async byUser(userId: string, tokenValue: string): Promise<Token> {
return this
.db(this.tableName)
.select(['id'])
.where('user_id', '=', userId)
.where('value', '=', tokenValue)
.first();
}
public async isValid(userId: string, tokenValue: string): Promise<boolean> {
const token = await this.byUser(userId, tokenValue);
return !!token;
}
public async deleteExpiredTokens() {
const cutOffDate = Date.now() - this.tokenTtl_;
await this.db(this.tableName).where('created_time', '<', cutOffDate).delete();
}
public async deleteByValue(userId: Uuid, value: string) {
const token = await this.byUser(userId, value);
if (token) await this.delete(token.id);
}
public async allByUserId(userId: Uuid): Promise<Token[]> {
return this
.db(this.tableName)
.select(this.defaultFields)
.where('user_id', '=', userId);
}
}

Some files were not shown because too many files have changed in this diff Show More