@jant/core 0.3.35 → 0.3.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/commands/export.js +1 -1
- package/bin/commands/import-site.js +529 -0
- package/bin/commands/reset-password.js +3 -2
- package/dist/client/assets/heic-to-DIRPI3VF.js +1 -0
- package/dist/client/assets/module-RjUF93sV.js +716 -0
- package/dist/client/assets/native-48B9X9Wg.js +1 -0
- package/dist/client/assets/url-FWFqPJPb.js +1 -0
- package/dist/client/client.css +1 -1
- package/dist/client/client.js +4564 -3013
- package/dist/index.js +12885 -8161
- package/package.json +23 -6
- package/src/__tests__/helpers/app.ts +10 -10
- package/src/__tests__/helpers/db.ts +91 -87
- package/src/app.tsx +157 -31
- package/src/auth.ts +20 -2
- package/src/client/archive-nav.js +187 -0
- package/src/client/audio-player.ts +478 -0
- package/src/client/audio-processor.ts +84 -0
- package/src/{lib → client}/avatar-upload.ts +4 -3
- package/src/{lib → client}/collection-form-bridge.ts +2 -2
- package/src/{ui → client}/components/__tests__/jant-collection-form.test.ts +26 -9
- package/src/client/components/__tests__/jant-compose-dialog.test.ts +1140 -0
- package/src/client/components/__tests__/jant-compose-editor.test.ts +504 -0
- package/src/{ui → client}/components/__tests__/jant-post-form.test.ts +37 -17
- package/src/{ui → client}/components/__tests__/jant-settings-avatar.test.ts +2 -2
- package/src/{ui → client}/components/__tests__/jant-settings-general.test.ts +3 -3
- package/src/client/components/collection-sidebar-types.ts +43 -0
- package/src/{ui → client}/components/collection-types.ts +3 -4
- package/src/client/components/compose-types.ts +174 -0
- package/src/client/components/jant-collection-form.ts +667 -0
- package/src/client/components/jant-collection-sidebar.ts +805 -0
- package/src/client/components/jant-compose-dialog.ts +2161 -0
- package/src/client/components/jant-compose-editor.ts +1813 -0
- package/src/client/components/jant-compose-fullscreen.ts +283 -0
- package/src/client/components/jant-media-lightbox.ts +259 -0
- package/src/{ui → client}/components/jant-nav-manager.ts +97 -298
- package/src/{ui → client}/components/jant-post-form.ts +141 -12
- package/src/client/components/jant-post-menu.ts +1019 -0
- package/src/{ui → client}/components/jant-settings-avatar.ts +3 -3
- package/src/{ui → client}/components/jant-settings-general.ts +38 -4
- package/src/client/components/jant-text-preview.ts +232 -0
- package/src/{ui → client}/components/nav-manager-types.ts +6 -18
- package/src/{ui → client}/components/post-form-template.ts +137 -38
- package/src/{ui → client}/components/post-form-types.ts +15 -4
- package/src/client/compose-bridge.ts +583 -0
- package/src/{lib → client}/image-processor.ts +26 -8
- package/src/client/lazy-slugify.ts +51 -0
- package/src/client/media-metadata.ts +247 -0
- package/src/client/multipart-upload.ts +160 -0
- package/src/{lib → client}/nav-manager-bridge.ts +1 -1
- package/src/{lib → client}/post-form-bridge.ts +53 -2
- package/src/{lib → client}/settings-bridge.ts +3 -15
- package/src/client/thread-context.ts +140 -0
- package/src/client/tiptap/bubble-menu.ts +205 -0
- package/src/client/tiptap/create-editor.ts +86 -0
- package/src/client/tiptap/exitable-marks.ts +73 -0
- package/src/client/tiptap/extensions.ts +65 -0
- package/src/client/tiptap/image-node.ts +482 -0
- package/src/client/tiptap/link-toolbar.ts +371 -0
- package/src/client/tiptap/more-break.ts +50 -0
- package/src/client/tiptap/paste-image.ts +129 -0
- package/src/client/tiptap/slash-commands.ts +438 -0
- package/src/{lib → client}/toast.ts +101 -3
- package/src/client/types/sortablejs.d.ts +44 -0
- package/src/client/upload-with-metadata.ts +54 -0
- package/src/client/video-processor.ts +207 -0
- package/src/client.ts +27 -17
- package/src/db/__tests__/migrations.test.ts +118 -0
- package/src/db/index.ts +52 -0
- package/src/db/migrations/0000_baseline.sql +269 -0
- package/src/db/migrations/0001_fts_setup.sql +31 -0
- package/src/db/migrations/meta/0000_snapshot.json +703 -119
- package/src/db/migrations/meta/0001_snapshot.json +1337 -0
- package/src/db/migrations/meta/_journal.json +4 -39
- package/src/db/schema.ts +409 -140
- package/src/i18n/__tests__/detect.test.ts +115 -0
- package/src/i18n/context.tsx +2 -2
- package/src/i18n/detect.ts +85 -1
- package/src/i18n/i18n.ts +1 -1
- package/src/i18n/index.ts +2 -1
- package/src/i18n/locales/en.po +783 -1087
- package/src/i18n/locales/en.ts +1 -1
- package/src/i18n/locales/zh-Hans.po +867 -812
- package/src/i18n/locales/zh-Hans.ts +1 -1
- package/src/i18n/locales/zh-Hant.po +878 -823
- package/src/i18n/locales/zh-Hant.ts +1 -1
- package/src/i18n/middleware.ts +6 -0
- package/src/index.ts +5 -7
- package/src/lib/__tests__/blurhash-placeholder.test.ts +75 -0
- package/src/lib/__tests__/constants.test.ts +0 -1
- package/src/lib/__tests__/markdown-to-tiptap.test.ts +358 -0
- package/src/lib/__tests__/nanoid.test.ts +26 -0
- package/src/lib/__tests__/resolve-config.test.ts +2 -2
- package/src/lib/__tests__/schemas.test.ts +186 -65
- package/src/lib/__tests__/slug.test.ts +126 -0
- package/src/lib/__tests__/sse.test.ts +6 -6
- package/src/lib/__tests__/summary.test.ts +264 -0
- package/src/lib/__tests__/theme.test.ts +1 -1
- package/src/lib/__tests__/timeline.test.ts +33 -30
- package/src/lib/__tests__/tiptap-to-markdown.test.ts +346 -0
- package/src/lib/__tests__/url.test.ts +2 -2
- package/src/lib/__tests__/view.test.ts +140 -65
- package/src/lib/blurhash-placeholder.ts +102 -0
- package/src/lib/constants.ts +3 -1
- package/src/lib/emoji-catalog.ts +963 -0
- package/src/lib/errors.ts +11 -8
- package/src/lib/feed.ts +77 -31
- package/src/lib/html.ts +2 -1
- package/src/lib/icon-catalog.ts +5033 -1
- package/src/lib/icons.ts +3 -2
- package/src/lib/index.ts +0 -1
- package/src/lib/markdown-to-tiptap.ts +286 -0
- package/src/lib/media-helpers.ts +22 -12
- package/src/lib/nanoid.ts +29 -0
- package/src/lib/navigation.ts +1 -1
- package/src/lib/render.tsx +24 -5
- package/src/lib/resolve-config.ts +13 -2
- package/src/lib/schemas.ts +226 -58
- package/src/lib/search-snippet.ts +34 -0
- package/src/lib/slug.ts +96 -0
- package/src/lib/sse.ts +6 -6
- package/src/lib/storage.ts +115 -7
- package/src/lib/summary.ts +158 -0
- package/src/lib/theme.ts +11 -8
- package/src/lib/timeline.ts +76 -34
- package/src/lib/tiptap-render.ts +191 -0
- package/src/lib/tiptap-to-markdown.ts +305 -0
- package/src/lib/upload.ts +263 -14
- package/src/lib/url.ts +37 -22
- package/src/lib/view.ts +236 -55
- package/src/middleware/__tests__/auth.test.ts +191 -11
- package/src/middleware/__tests__/onboarding.test.ts +12 -10
- package/src/middleware/auth.ts +63 -9
- package/src/middleware/error-handler.ts +3 -3
- package/src/middleware/onboarding.ts +1 -1
- package/src/middleware/secure-headers.ts +40 -0
- package/src/preset.css +83 -2
- package/src/routes/__tests__/compose.test.ts +17 -24
- package/src/routes/api/__tests__/collections.test.ts +109 -61
- package/src/routes/api/__tests__/nav-items.test.ts +46 -29
- package/src/routes/api/__tests__/posts.test.ts +132 -68
- package/src/routes/api/__tests__/search.test.ts +15 -2
- package/src/routes/api/__tests__/upload-multipart.test.ts +534 -0
- package/src/routes/api/collections.ts +57 -31
- package/src/routes/api/custom-urls.ts +80 -0
- package/src/routes/api/export.ts +31 -0
- package/src/routes/api/nav-items.ts +23 -19
- package/src/routes/api/posts.ts +81 -62
- package/src/routes/api/search.ts +3 -4
- package/src/routes/api/upload-multipart.ts +245 -0
- package/src/routes/api/upload.ts +92 -24
- package/src/routes/auth/__tests__/setup.test.ts +20 -60
- package/src/routes/auth/reset.tsx +5 -4
- package/src/routes/auth/setup.tsx +39 -31
- package/src/routes/auth/signin.tsx +13 -14
- package/src/routes/compose.tsx +27 -63
- package/src/routes/dash/__tests__/settings-avatar.test.ts +44 -9
- package/src/routes/dash/custom-urls.tsx +414 -0
- package/src/routes/dash/settings.tsx +475 -99
- package/src/routes/feed/__tests__/rss.test.ts +22 -23
- package/src/routes/feed/rss.ts +6 -2
- package/src/routes/feed/sitemap.ts +2 -12
- package/src/routes/pages/__tests__/collections.test.ts +5 -6
- package/src/routes/pages/__tests__/featured.test.ts +36 -18
- package/src/routes/pages/archive.tsx +177 -37
- package/src/routes/pages/collection.tsx +43 -14
- package/src/routes/pages/collections.tsx +11 -2
- package/src/routes/pages/featured.tsx +27 -3
- package/src/routes/pages/home.tsx +15 -14
- package/src/routes/pages/latest.tsx +1 -11
- package/src/routes/pages/new.tsx +39 -0
- package/src/routes/pages/page.tsx +95 -49
- package/src/routes/pages/search.tsx +1 -1
- package/src/services/__tests__/api-token.test.ts +135 -0
- package/src/services/__tests__/collection.test.ts +275 -227
- package/src/services/__tests__/custom-url.test.ts +213 -0
- package/src/services/__tests__/media.test.ts +162 -22
- package/src/services/__tests__/navigation.test.ts +109 -68
- package/src/services/__tests__/post-timeline.test.ts +205 -32
- package/src/services/__tests__/post.test.ts +800 -230
- package/src/services/__tests__/search.test.ts +67 -10
- package/src/services/__tests__/settings.test.ts +3 -3
- package/src/services/api-token.ts +166 -0
- package/src/services/auth.ts +17 -2
- package/src/services/collection.ts +397 -131
- package/src/services/custom-url.ts +188 -0
- package/src/services/export.ts +802 -0
- package/src/services/index.ts +26 -19
- package/src/services/media.ts +100 -22
- package/src/services/navigation.ts +158 -47
- package/src/services/path.ts +339 -0
- package/src/services/post.ts +764 -172
- package/src/services/search.ts +161 -74
- package/src/services/settings.ts +6 -2
- package/src/styles/components.css +293 -62
- package/src/styles/tokens.css +93 -5
- package/src/styles/ui.css +4349 -766
- package/src/types/bindings.ts +8 -0
- package/src/types/config.ts +34 -4
- package/src/types/constants.ts +17 -2
- package/src/types/entities.ts +83 -37
- package/src/types/operations.ts +20 -27
- package/src/types/props.ts +52 -17
- package/src/types/views.ts +48 -24
- package/src/ui/color-themes.ts +133 -23
- package/src/ui/compose/ComposeDialog.tsx +255 -16
- package/src/ui/compose/ComposePrompt.tsx +1 -1
- package/src/ui/dash/CrudPageHeader.tsx +1 -1
- package/src/ui/dash/ListItemRow.tsx +1 -1
- package/src/ui/dash/StatusBadge.tsx +12 -2
- package/src/ui/dash/appearance/AdvancedContent.tsx +71 -59
- package/src/ui/dash/appearance/ColorThemeContent.tsx +48 -33
- package/src/ui/dash/appearance/FontThemeContent.tsx +65 -73
- package/src/ui/dash/appearance/NavigationContent.tsx +106 -135
- package/src/ui/dash/index.ts +0 -3
- package/src/ui/dash/settings/AccountContent.tsx +87 -146
- package/src/ui/dash/settings/AccountMenuContent.tsx +147 -0
- package/src/ui/dash/settings/ApiTokensContent.tsx +232 -0
- package/src/ui/dash/settings/AvatarContent.tsx +78 -0
- package/src/ui/dash/settings/GeneralContent.tsx +3 -62
- package/src/ui/dash/settings/SessionsContent.tsx +159 -0
- package/src/ui/dash/settings/SettingsRootContent.tsx +266 -0
- package/src/ui/feed/LinkCard.tsx +89 -40
- package/src/ui/feed/NoteCard.tsx +39 -25
- package/src/ui/feed/PostStatusBadges.tsx +67 -0
- package/src/ui/feed/QuoteCard.tsx +38 -23
- package/src/ui/feed/ThreadPreview.tsx +90 -26
- package/src/ui/feed/TimelineFeed.tsx +3 -2
- package/src/ui/feed/TimelineItem.tsx +15 -6
- package/src/ui/feed/__tests__/thread-preview.test.ts +107 -0
- package/src/ui/feed/thread-preview-state.ts +61 -0
- package/src/ui/font-themes.ts +2 -2
- package/src/ui/layouts/BaseLayout.tsx +2 -2
- package/src/ui/layouts/SiteLayout.tsx +116 -103
- package/src/ui/pages/ArchivePage.tsx +923 -95
- package/src/ui/pages/CollectionPage.tsx +6 -35
- package/src/ui/pages/CollectionsPage.tsx +2 -1
- package/src/ui/pages/ComposePage.tsx +54 -0
- package/src/ui/pages/FeaturedPage.tsx +2 -1
- package/src/ui/pages/HomePage.tsx +1 -1
- package/src/ui/pages/PostPage.tsx +30 -45
- package/src/ui/pages/SearchPage.tsx +182 -38
- package/src/ui/shared/AdminBreadcrumb.tsx +29 -0
- package/src/ui/shared/CollectionsSidebar.tsx +239 -4
- package/src/ui/shared/MediaGallery.tsx +475 -41
- package/src/ui/shared/PostFooter.tsx +204 -0
- package/src/ui/shared/StarRating.tsx +27 -0
- package/src/ui/shared/__tests__/format-chars.test.ts +35 -0
- package/src/ui/shared/index.ts +0 -1
- package/src/db/migrations/0000_square_wallflower.sql +0 -118
- package/src/db/migrations/0001_add_search_fts.sql +0 -34
- package/src/db/migrations/0002_add_media_attachments.sql +0 -3
- package/src/db/migrations/0003_add_navigation_links.sql +0 -8
- package/src/db/migrations/0004_add_storage_provider.sql +0 -3
- package/src/db/migrations/0005_v2_schema_migration.sql +0 -268
- package/src/db/migrations/0006_rename_slug_to_path.sql +0 -5
- package/src/db/migrations/0007_post_collections_m2m.sql +0 -94
- package/src/db/migrations/0008_add_collection_dividers.sql +0 -8
- package/src/db/migrations/0009_drop_collection_show_divider.sql +0 -2
- package/src/db/migrations/0010_add_performance_indexes.sql +0 -16
- package/src/db/migrations/0011_add_path_registry.sql +0 -23
- package/src/db/migrations/meta/0003_snapshot.json +0 -821
- package/src/lib/__tests__/sqid.test.ts +0 -65
- package/src/lib/collections-reorder.ts +0 -28
- package/src/lib/compose-bridge.ts +0 -280
- package/src/lib/media-upload.ts +0 -148
- package/src/lib/sqid.ts +0 -79
- package/src/routes/api/__tests__/pages.test.ts +0 -218
- package/src/routes/api/pages.ts +0 -73
- package/src/routes/dash/__tests__/pages.test.ts +0 -226
- package/src/routes/dash/appearance.tsx +0 -240
- package/src/routes/dash/collections.tsx +0 -211
- package/src/routes/dash/index.tsx +0 -103
- package/src/routes/dash/media.tsx +0 -132
- package/src/routes/dash/pages.tsx +0 -239
- package/src/routes/dash/posts.tsx +0 -334
- package/src/routes/dash/redirects.tsx +0 -257
- package/src/routes/pages/post.tsx +0 -59
- package/src/services/__tests__/page.test.ts +0 -298
- package/src/services/__tests__/path-registry.test.ts +0 -165
- package/src/services/__tests__/redirect.test.ts +0 -159
- package/src/services/page.ts +0 -203
- package/src/services/path-registry.ts +0 -160
- package/src/services/redirect.ts +0 -97
- package/src/types/sortablejs.d.ts +0 -29
- package/src/ui/components/__tests__/jant-compose-dialog.test.ts +0 -512
- package/src/ui/components/__tests__/jant-compose-editor.test.ts +0 -272
- package/src/ui/components/compose-types.ts +0 -75
- package/src/ui/components/jant-collection-form.ts +0 -512
- package/src/ui/components/jant-compose-dialog.ts +0 -495
- package/src/ui/components/jant-compose-editor.ts +0 -814
- package/src/ui/dash/PageForm.tsx +0 -185
- package/src/ui/dash/PostList.tsx +0 -95
- package/src/ui/dash/appearance/AppearanceNav.tsx +0 -60
- package/src/ui/dash/collections/CollectionForm.tsx +0 -166
- package/src/ui/dash/collections/CollectionsListContent.tsx +0 -146
- package/src/ui/dash/collections/IconPickerGrid.tsx +0 -50
- package/src/ui/dash/collections/ViewCollectionContent.tsx +0 -103
- package/src/ui/dash/media/MediaListContent.tsx +0 -201
- package/src/ui/dash/media/ViewMediaContent.tsx +0 -208
- package/src/ui/dash/pages/PagesContent.tsx +0 -74
- package/src/ui/dash/posts/PostForm.tsx +0 -248
- package/src/ui/dash/settings/SettingsNav.tsx +0 -52
- package/src/ui/layouts/DashLayout.tsx +0 -165
- package/src/ui/pages/SinglePage.tsx +0 -23
- package/src/ui/shared/ThreadView.tsx +0 -136
- /package/src/{ui → client}/components/settings-types.ts +0 -0
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
// @vitest-environment happy-dom
|
|
2
|
+
|
|
3
|
+
import { describe, it, expect, beforeEach } from "vitest";
|
|
4
|
+
import type { ComposeLabels } from "../compose-types.js";
|
|
5
|
+
import "../jant-compose-editor.js";
|
|
6
|
+
import type { JantComposeEditor } from "../jant-compose-editor.js";
|
|
7
|
+
|
|
8
|
+
function requireElement<T extends globalThis.Element>(
|
|
9
|
+
element: T | null,
|
|
10
|
+
message: string,
|
|
11
|
+
): T {
|
|
12
|
+
if (!element) {
|
|
13
|
+
throw new Error(message);
|
|
14
|
+
}
|
|
15
|
+
return element;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function requireItem<T extends globalThis.Element>(
|
|
19
|
+
collection: globalThis.NodeListOf<T>,
|
|
20
|
+
index: number,
|
|
21
|
+
message: string,
|
|
22
|
+
): T {
|
|
23
|
+
const item = collection.item(index);
|
|
24
|
+
if (!item) {
|
|
25
|
+
throw new Error(message);
|
|
26
|
+
}
|
|
27
|
+
return item;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const labels: ComposeLabels = {
|
|
31
|
+
cancel: "Cancel",
|
|
32
|
+
note: "Note",
|
|
33
|
+
link: "Link",
|
|
34
|
+
quote: "Quote",
|
|
35
|
+
saveDraft: "Save as Draft",
|
|
36
|
+
saveAsDraft: "Save as draft",
|
|
37
|
+
discard: "Discard",
|
|
38
|
+
titlePlaceholder: "Title",
|
|
39
|
+
bodyPlaceholder: "What's on your mind...",
|
|
40
|
+
urlPlaceholder: "Paste a URL...",
|
|
41
|
+
linkTitlePlaceholder: "Give it a title...",
|
|
42
|
+
thoughtsPlaceholder: "Your thoughts (optional)",
|
|
43
|
+
quotePlaceholder: "Type the quote...",
|
|
44
|
+
authorPlaceholder: "Author (optional)",
|
|
45
|
+
sourcePlaceholder: "Source link (optional)",
|
|
46
|
+
attachedText: "Attached Text",
|
|
47
|
+
attachedTextPlaceholder: "Paste text...",
|
|
48
|
+
attachedTextHint: "Supplementary content",
|
|
49
|
+
done: "Done",
|
|
50
|
+
media: "Media",
|
|
51
|
+
rate: "Rate",
|
|
52
|
+
emoji: "Emoji",
|
|
53
|
+
title: "Title",
|
|
54
|
+
collection: "Collection",
|
|
55
|
+
searchCollections: "Search...",
|
|
56
|
+
noCollections: "No collections found.",
|
|
57
|
+
emptyCollections: "Create a collection to get started.",
|
|
58
|
+
post: "Post",
|
|
59
|
+
addAlt: "+ ALT",
|
|
60
|
+
addAltTitle: "Add alt text",
|
|
61
|
+
altPlaceholder: "Describe this...",
|
|
62
|
+
altHint: "Alt text improves accessibility",
|
|
63
|
+
addMore: "Add",
|
|
64
|
+
uploading: "Uploading...",
|
|
65
|
+
published: "Published!",
|
|
66
|
+
view: "View",
|
|
67
|
+
retryAll: "Tap to retry",
|
|
68
|
+
editPost: "Edit post",
|
|
69
|
+
update: "Done",
|
|
70
|
+
confirmCloseTitle: "Save to drafts?",
|
|
71
|
+
confirmCloseSubtitle: "Save to drafts to edit and post at a later time.",
|
|
72
|
+
confirmCloseSave: "Save",
|
|
73
|
+
confirmCloseCancel: "Cancel",
|
|
74
|
+
confirmCloseDiscard: "Don't save",
|
|
75
|
+
confirmEditTitle: "You have unsaved changes",
|
|
76
|
+
confirmEditSubtitle: "Do you want to publish your changes or discard them?",
|
|
77
|
+
confirmEditPublish: "Publish",
|
|
78
|
+
confirmEditDiscard: "Discard",
|
|
79
|
+
drafts: "Drafts",
|
|
80
|
+
draftsEmpty: "No drafts yet. Save a draft to find it here.",
|
|
81
|
+
deleteDraft: "Delete Draft",
|
|
82
|
+
draftDeleted: "Draft deleted.",
|
|
83
|
+
publishFailedDraft: "Couldn't publish. Saved as draft.",
|
|
84
|
+
uploadFailedDraft: "Some uploads failed. Saved as draft.",
|
|
85
|
+
addCollection: "Add Collection",
|
|
86
|
+
collectionCountLabel: "%name% + %count% more",
|
|
87
|
+
draftRestored: "Draft restored.",
|
|
88
|
+
reply: "Reply",
|
|
89
|
+
publishFeatured: "Post as Featured",
|
|
90
|
+
publishUnlisted: "Post Unlisted",
|
|
91
|
+
publishPrivate: "Post as Private",
|
|
92
|
+
showMore: "Show more",
|
|
93
|
+
showLess: "Show less",
|
|
94
|
+
collectionFormLabels: {
|
|
95
|
+
titleLabel: "Title",
|
|
96
|
+
titlePlaceholder: "My Collection",
|
|
97
|
+
slugLabel: "Slug",
|
|
98
|
+
slugHelp: "URL-safe identifier",
|
|
99
|
+
descriptionLabel: "Description (optional)",
|
|
100
|
+
descriptionPlaceholder: "What's this collection about?",
|
|
101
|
+
removeIcon: "Remove",
|
|
102
|
+
iconsTab: "Icons",
|
|
103
|
+
emojisTab: "Emojis",
|
|
104
|
+
searchIconsPlaceholder: "Search icons...",
|
|
105
|
+
searchEmojisPlaceholder: "Search emojis...",
|
|
106
|
+
sortOrderLabel: "Sort Order",
|
|
107
|
+
sortNewest: "Newest first",
|
|
108
|
+
sortOldest: "Oldest first",
|
|
109
|
+
sortRatingDesc: "Highest rated",
|
|
110
|
+
sortRatingAsc: "Lowest rated",
|
|
111
|
+
submitLabel: "Save",
|
|
112
|
+
cancelLabel: "Cancel",
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
async function createElement(
|
|
117
|
+
format: string = "note",
|
|
118
|
+
): Promise<JantComposeEditor> {
|
|
119
|
+
const el = document.createElement("jant-compose-editor") as JantComposeEditor;
|
|
120
|
+
el.format = format as "note" | "link" | "quote";
|
|
121
|
+
el.labels = labels;
|
|
122
|
+
document.body.appendChild(el);
|
|
123
|
+
await el.updateComplete;
|
|
124
|
+
return el;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
describe("JantComposeEditor", () => {
|
|
128
|
+
beforeEach(() => {
|
|
129
|
+
document.body.innerHTML = "";
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("renders note fields by default", async () => {
|
|
133
|
+
const el = await createElement("note");
|
|
134
|
+
const tiptapContainer = requireElement(
|
|
135
|
+
el.querySelector<HTMLElement>(".compose-tiptap-body"),
|
|
136
|
+
"expected compose Tiptap body container",
|
|
137
|
+
);
|
|
138
|
+
expect(tiptapContainer).toBeTruthy();
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
it("renders link fields when format is link", async () => {
|
|
142
|
+
const el = await createElement("link");
|
|
143
|
+
const urlInput = requireElement(
|
|
144
|
+
el.querySelector<HTMLInputElement>('input[type="url"]'),
|
|
145
|
+
"expected url input",
|
|
146
|
+
);
|
|
147
|
+
expect(urlInput.placeholder).toBe("Paste a URL...");
|
|
148
|
+
|
|
149
|
+
const titleInput = el.querySelector<HTMLInputElement>(
|
|
150
|
+
".compose-link-title",
|
|
151
|
+
);
|
|
152
|
+
expect(titleInput).not.toBeNull();
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("renders quote fields when format is quote", async () => {
|
|
156
|
+
const el = await createElement("quote");
|
|
157
|
+
const quoteTextarea = el.querySelector<HTMLTextAreaElement>(
|
|
158
|
+
".compose-quote-text",
|
|
159
|
+
);
|
|
160
|
+
expect(quoteTextarea).not.toBeNull();
|
|
161
|
+
|
|
162
|
+
const authorInput = el.querySelector<HTMLInputElement>(
|
|
163
|
+
".compose-quote-author",
|
|
164
|
+
);
|
|
165
|
+
expect(authorInput).not.toBeNull();
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
it("toggles star rating visibility", async () => {
|
|
169
|
+
const el = await createElement("note");
|
|
170
|
+
|
|
171
|
+
// Rating not visible initially
|
|
172
|
+
expect(el.querySelector(".compose-star-rating")).toBeNull();
|
|
173
|
+
|
|
174
|
+
// Click score button to show rating
|
|
175
|
+
const toolButtons =
|
|
176
|
+
el.querySelectorAll<HTMLButtonElement>(".compose-tool-btn");
|
|
177
|
+
const scoreBtnEl = requireItem(
|
|
178
|
+
toolButtons,
|
|
179
|
+
2,
|
|
180
|
+
"expected score tool button",
|
|
181
|
+
);
|
|
182
|
+
scoreBtnEl.click();
|
|
183
|
+
await el.updateComplete;
|
|
184
|
+
|
|
185
|
+
expect(el.querySelector(".compose-star-rating")).not.toBeNull();
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("sets rating on star click and deselects on same star", async () => {
|
|
189
|
+
const el = await createElement("note");
|
|
190
|
+
el._showRating = true;
|
|
191
|
+
await el.updateComplete;
|
|
192
|
+
|
|
193
|
+
const stars = el.querySelectorAll<HTMLButtonElement>(".compose-star");
|
|
194
|
+
expect(stars.length).toBe(5);
|
|
195
|
+
|
|
196
|
+
// Click third star
|
|
197
|
+
stars[2].click();
|
|
198
|
+
await el.updateComplete;
|
|
199
|
+
expect(el._rating).toBe(3);
|
|
200
|
+
|
|
201
|
+
// Rating label shows
|
|
202
|
+
const label = el.querySelector(".compose-star-label");
|
|
203
|
+
expect(label?.textContent).toContain("3/5");
|
|
204
|
+
|
|
205
|
+
// Click third star again to deselect
|
|
206
|
+
stars[2].click();
|
|
207
|
+
await el.updateComplete;
|
|
208
|
+
expect(el._rating).toBe(0);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it("dispatches attached panel open event and creates new item", async () => {
|
|
212
|
+
const el = await createElement("note");
|
|
213
|
+
|
|
214
|
+
const events: CustomEvent[] = [];
|
|
215
|
+
el.addEventListener("jant:attached-panel-open", (e) =>
|
|
216
|
+
events.push(e as CustomEvent),
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
// Click attached text tool button
|
|
220
|
+
const toolBtns =
|
|
221
|
+
el.querySelectorAll<HTMLButtonElement>(".compose-tool-btn");
|
|
222
|
+
const attachedBtn = requireItem(
|
|
223
|
+
toolBtns,
|
|
224
|
+
1,
|
|
225
|
+
"expected attached text button",
|
|
226
|
+
);
|
|
227
|
+
attachedBtn.click();
|
|
228
|
+
await el.updateComplete;
|
|
229
|
+
|
|
230
|
+
expect(events).toHaveLength(1);
|
|
231
|
+
expect(events[0].detail.index).toBe(0);
|
|
232
|
+
expect(el._attachedTexts).toHaveLength(1);
|
|
233
|
+
expect(el._attachedTexts[0].bodyJson).toBeNull();
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it("shows title toggle only in note mode", async () => {
|
|
237
|
+
const el = await createElement("note");
|
|
238
|
+
const toolSep = el.querySelector(".compose-tool-sep");
|
|
239
|
+
expect(toolSep).not.toBeNull();
|
|
240
|
+
|
|
241
|
+
el.format = "link";
|
|
242
|
+
await el.updateComplete;
|
|
243
|
+
expect(el.querySelector(".compose-tool-sep")).toBeNull();
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
it("getData returns current field values", async () => {
|
|
247
|
+
const el = await createElement("note");
|
|
248
|
+
el._title = "Test Title";
|
|
249
|
+
el._showTitle = true;
|
|
250
|
+
el._bodyJson = {
|
|
251
|
+
type: "doc",
|
|
252
|
+
content: [
|
|
253
|
+
{ type: "paragraph", content: [{ type: "text", text: "Test Body" }] },
|
|
254
|
+
],
|
|
255
|
+
};
|
|
256
|
+
el._rating = 4;
|
|
257
|
+
el._attachedTexts = [
|
|
258
|
+
{
|
|
259
|
+
clientId: "t1",
|
|
260
|
+
bodyJson: {
|
|
261
|
+
type: "doc",
|
|
262
|
+
content: [
|
|
263
|
+
{
|
|
264
|
+
type: "paragraph",
|
|
265
|
+
content: [{ type: "text", text: "Some attached text" }],
|
|
266
|
+
},
|
|
267
|
+
],
|
|
268
|
+
},
|
|
269
|
+
summary: "Some attached text",
|
|
270
|
+
bodyHtml: "<p>Some attached text</p>",
|
|
271
|
+
},
|
|
272
|
+
];
|
|
273
|
+
|
|
274
|
+
const data = el.getData();
|
|
275
|
+
expect(data.title).toBe("Test Title");
|
|
276
|
+
expect(data.body).toContain("Test Body");
|
|
277
|
+
expect(data.rating).toBe(4);
|
|
278
|
+
expect(data.attachedTexts).toHaveLength(1);
|
|
279
|
+
expect(data.attachedTexts[0].bodyJson).not.toBeNull();
|
|
280
|
+
expect(data.url).toBe("");
|
|
281
|
+
expect(data.quoteText).toBe("");
|
|
282
|
+
expect(data.quoteAuthor).toBe("");
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
it("getData omits title when showTitle is off in note mode", async () => {
|
|
286
|
+
const el = await createElement("note");
|
|
287
|
+
el._title = "Hidden Title";
|
|
288
|
+
el._showTitle = false;
|
|
289
|
+
|
|
290
|
+
const data = el.getData();
|
|
291
|
+
expect(data.title).toBe("");
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
it("preserves title in memory when toggling off and restores on toggle on", async () => {
|
|
295
|
+
const el = await createElement("note");
|
|
296
|
+
el._title = "My Title";
|
|
297
|
+
el._showTitle = true;
|
|
298
|
+
await el.updateComplete;
|
|
299
|
+
|
|
300
|
+
// Toggle off — title stays in memory
|
|
301
|
+
el._showTitle = false;
|
|
302
|
+
await el.updateComplete;
|
|
303
|
+
expect(el._title).toBe("My Title");
|
|
304
|
+
expect(el.getData().title).toBe("");
|
|
305
|
+
|
|
306
|
+
// Toggle back on — title restored
|
|
307
|
+
el._showTitle = true;
|
|
308
|
+
await el.updateComplete;
|
|
309
|
+
expect(el.getData().title).toBe("My Title");
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
it("reset clears all fields", async () => {
|
|
313
|
+
const el = await createElement("note");
|
|
314
|
+
el._title = "Test";
|
|
315
|
+
el._bodyJson = {
|
|
316
|
+
type: "doc",
|
|
317
|
+
content: [
|
|
318
|
+
{ type: "paragraph", content: [{ type: "text", text: "Body" }] },
|
|
319
|
+
],
|
|
320
|
+
};
|
|
321
|
+
el._rating = 3;
|
|
322
|
+
el._showRating = true;
|
|
323
|
+
el._attachedTexts = [
|
|
324
|
+
{
|
|
325
|
+
clientId: "t1",
|
|
326
|
+
bodyJson: {
|
|
327
|
+
type: "doc",
|
|
328
|
+
content: [
|
|
329
|
+
{
|
|
330
|
+
type: "paragraph",
|
|
331
|
+
content: [{ type: "text", text: "text" }],
|
|
332
|
+
},
|
|
333
|
+
],
|
|
334
|
+
},
|
|
335
|
+
summary: "text",
|
|
336
|
+
bodyHtml: "<p>text</p>",
|
|
337
|
+
},
|
|
338
|
+
];
|
|
339
|
+
|
|
340
|
+
el.reset();
|
|
341
|
+
|
|
342
|
+
expect(el._title).toBe("");
|
|
343
|
+
expect(el._bodyJson).toBeNull();
|
|
344
|
+
expect(el._rating).toBe(0);
|
|
345
|
+
expect(el._showRating).toBe(false);
|
|
346
|
+
expect(el._attachedTexts).toEqual([]);
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
it("shows attached text card in attachment strip", async () => {
|
|
350
|
+
const el = await createElement("note");
|
|
351
|
+
el._attachedTexts = [
|
|
352
|
+
{
|
|
353
|
+
clientId: "t1",
|
|
354
|
+
bodyJson: {
|
|
355
|
+
type: "doc",
|
|
356
|
+
content: [
|
|
357
|
+
{
|
|
358
|
+
type: "paragraph",
|
|
359
|
+
content: [{ type: "text", text: "Some content here" }],
|
|
360
|
+
},
|
|
361
|
+
],
|
|
362
|
+
},
|
|
363
|
+
summary: "Some content here",
|
|
364
|
+
bodyHtml: "<p>Some content here</p>",
|
|
365
|
+
},
|
|
366
|
+
];
|
|
367
|
+
el._attachmentOrder = ["t1"];
|
|
368
|
+
await el.updateComplete;
|
|
369
|
+
|
|
370
|
+
const card = el.querySelector(".compose-attachment-text-card");
|
|
371
|
+
expect(card).not.toBeNull();
|
|
372
|
+
expect(card?.textContent).toContain("Some content here");
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
it("media button shows inline add label when attachments are present", async () => {
|
|
376
|
+
const el = await createElement("note");
|
|
377
|
+
|
|
378
|
+
// Media button should not have add style initially
|
|
379
|
+
const mediaBtn = el.querySelector<HTMLButtonElement>(".compose-tool-btn");
|
|
380
|
+
expect(mediaBtn?.classList.contains("compose-tool-btn-add")).toBe(false);
|
|
381
|
+
|
|
382
|
+
// Add an attachment
|
|
383
|
+
const blob = new Blob(["fake"], { type: "image/png" });
|
|
384
|
+
const file = new File([blob], "test.png", { type: "image/png" });
|
|
385
|
+
el._attachments = [
|
|
386
|
+
{
|
|
387
|
+
clientId: "test-1",
|
|
388
|
+
file,
|
|
389
|
+
previewUrl: URL.createObjectURL(blob),
|
|
390
|
+
status: "done",
|
|
391
|
+
progress: null,
|
|
392
|
+
mediaId: "m1",
|
|
393
|
+
alt: "",
|
|
394
|
+
error: null,
|
|
395
|
+
summary: null,
|
|
396
|
+
chars: null,
|
|
397
|
+
},
|
|
398
|
+
];
|
|
399
|
+
await el.updateComplete;
|
|
400
|
+
|
|
401
|
+
const mediaBtnAfter =
|
|
402
|
+
el.querySelector<HTMLButtonElement>(".compose-tool-btn");
|
|
403
|
+
expect(mediaBtnAfter?.classList.contains("compose-tool-btn-add")).toBe(
|
|
404
|
+
true,
|
|
405
|
+
);
|
|
406
|
+
|
|
407
|
+
// Should show inline label, not tooltip
|
|
408
|
+
const label = mediaBtnAfter?.querySelector(".compose-tool-label");
|
|
409
|
+
expect(label).not.toBeNull();
|
|
410
|
+
expect(label?.textContent).toBe("Add");
|
|
411
|
+
});
|
|
412
|
+
|
|
413
|
+
it("moves attachments later with keyboard controls", async () => {
|
|
414
|
+
const el = await createElement("note");
|
|
415
|
+
const blob = new Blob(["fake"], { type: "image/png" });
|
|
416
|
+
const file = new File([blob], "test.png", { type: "image/png" });
|
|
417
|
+
el._attachments = [
|
|
418
|
+
{
|
|
419
|
+
clientId: "a1",
|
|
420
|
+
file,
|
|
421
|
+
previewUrl: URL.createObjectURL(blob),
|
|
422
|
+
status: "done",
|
|
423
|
+
progress: null,
|
|
424
|
+
mediaId: "m1",
|
|
425
|
+
alt: "",
|
|
426
|
+
error: null,
|
|
427
|
+
summary: null,
|
|
428
|
+
chars: null,
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
clientId: "a2",
|
|
432
|
+
file,
|
|
433
|
+
previewUrl: URL.createObjectURL(blob),
|
|
434
|
+
status: "done",
|
|
435
|
+
progress: null,
|
|
436
|
+
mediaId: "m2",
|
|
437
|
+
alt: "",
|
|
438
|
+
error: null,
|
|
439
|
+
summary: null,
|
|
440
|
+
chars: null,
|
|
441
|
+
},
|
|
442
|
+
];
|
|
443
|
+
el._attachmentOrder = ["a1", "a2"];
|
|
444
|
+
await el.updateComplete;
|
|
445
|
+
|
|
446
|
+
const attachment = requireElement(
|
|
447
|
+
el.querySelector<HTMLElement>(
|
|
448
|
+
'[data-attachment-id="a1"] [data-attachment-sortable]',
|
|
449
|
+
),
|
|
450
|
+
"expected attachment card",
|
|
451
|
+
);
|
|
452
|
+
attachment.dispatchEvent(
|
|
453
|
+
new globalThis.KeyboardEvent("keydown", {
|
|
454
|
+
key: "ArrowRight",
|
|
455
|
+
bubbles: true,
|
|
456
|
+
}),
|
|
457
|
+
);
|
|
458
|
+
await el.updateComplete;
|
|
459
|
+
|
|
460
|
+
expect(el._attachmentOrder).toEqual(["a2", "a1"]);
|
|
461
|
+
});
|
|
462
|
+
|
|
463
|
+
it("preserves mixed attachment order when populate provides one", async () => {
|
|
464
|
+
const el = await createElement("note");
|
|
465
|
+
|
|
466
|
+
el.populate({
|
|
467
|
+
format: "note",
|
|
468
|
+
media: [
|
|
469
|
+
{
|
|
470
|
+
id: "m1",
|
|
471
|
+
previewUrl: "/a.png",
|
|
472
|
+
mimeType: "image/png",
|
|
473
|
+
},
|
|
474
|
+
],
|
|
475
|
+
textAttachments: [
|
|
476
|
+
{
|
|
477
|
+
clientId: "t1",
|
|
478
|
+
bodyJson: JSON.stringify({
|
|
479
|
+
type: "doc",
|
|
480
|
+
content: [
|
|
481
|
+
{
|
|
482
|
+
type: "paragraph",
|
|
483
|
+
content: [{ type: "text", text: "Text attachment" }],
|
|
484
|
+
},
|
|
485
|
+
],
|
|
486
|
+
}),
|
|
487
|
+
bodyHtml: "<p>Text attachment</p>",
|
|
488
|
+
summary: "Text attachment",
|
|
489
|
+
},
|
|
490
|
+
],
|
|
491
|
+
attachmentOrder: ["t1", "m1"],
|
|
492
|
+
});
|
|
493
|
+
await el.updateComplete;
|
|
494
|
+
|
|
495
|
+
const items = [
|
|
496
|
+
...el.querySelectorAll<HTMLElement>("[data-attachment-id]"),
|
|
497
|
+
].map((item) => item.dataset.attachmentId);
|
|
498
|
+
|
|
499
|
+
expect(items).toHaveLength(2);
|
|
500
|
+
expect(items[0]).toBe(el._attachmentOrder[0]);
|
|
501
|
+
expect(items[1]).toBe(el._attachmentOrder[1]);
|
|
502
|
+
expect(el._attachmentOrder[0]).toBe("t1");
|
|
503
|
+
});
|
|
504
|
+
});
|
|
@@ -18,6 +18,9 @@ const labels: PostFormLabels = {
|
|
|
18
18
|
quoteOption: "Quote",
|
|
19
19
|
titleLabel: "Title",
|
|
20
20
|
titlePlaceholder: "Title...",
|
|
21
|
+
slugLabel: "Slug",
|
|
22
|
+
slugPlaceholder: "auto-generated",
|
|
23
|
+
slugHelp: "Auto-generated from title",
|
|
21
24
|
bodyLabel: "Body",
|
|
22
25
|
bodyPlaceholder: "Body...",
|
|
23
26
|
urlLabel: "URL",
|
|
@@ -31,7 +34,9 @@ const labels: PostFormLabels = {
|
|
|
31
34
|
statusLabel: "Status",
|
|
32
35
|
statusPublished: "Published",
|
|
33
36
|
statusDraft: "Draft",
|
|
34
|
-
|
|
37
|
+
visibilityLabel: "Visibility",
|
|
38
|
+
visibilityPublic: "Public",
|
|
39
|
+
visibilityUnlisted: "Unlisted",
|
|
35
40
|
pinnedLabel: "Pinned",
|
|
36
41
|
collectionsLabel: "Collections",
|
|
37
42
|
submitLabel: "Publish",
|
|
@@ -41,16 +46,18 @@ const labels: PostFormLabels = {
|
|
|
41
46
|
mediaDialogLoading: "Loading...",
|
|
42
47
|
submitSuccessMessage: "Saved!",
|
|
43
48
|
submitErrorMessage: "Failed.",
|
|
49
|
+
draftFallbackMessage: "Couldn't publish. Saved as draft.",
|
|
44
50
|
};
|
|
45
51
|
|
|
46
52
|
const initial: PostFormInitial = {
|
|
47
53
|
format: "note",
|
|
48
54
|
title: "",
|
|
55
|
+
slug: "",
|
|
49
56
|
body: "",
|
|
50
57
|
url: "",
|
|
51
58
|
quoteText: "",
|
|
52
59
|
status: "published",
|
|
53
|
-
|
|
60
|
+
visibility: "public",
|
|
54
61
|
pinned: false,
|
|
55
62
|
rating: 0,
|
|
56
63
|
collectionIds: [],
|
|
@@ -63,7 +70,13 @@ const collections: PostCollectionOption[] = [
|
|
|
63
70
|
];
|
|
64
71
|
|
|
65
72
|
const media: PostMediaItem[] = [
|
|
66
|
-
{
|
|
73
|
+
{
|
|
74
|
+
id: "m1",
|
|
75
|
+
thumbUrl: "https://cdn.example.com/m1.jpg",
|
|
76
|
+
alt: "Media 1",
|
|
77
|
+
mimeType: "image/jpeg",
|
|
78
|
+
originalName: "photo.jpg",
|
|
79
|
+
},
|
|
67
80
|
];
|
|
68
81
|
|
|
69
82
|
async function createElement(
|
|
@@ -74,7 +87,7 @@ async function createElement(
|
|
|
74
87
|
el.initial = { ...initial };
|
|
75
88
|
el.collections = [...collections];
|
|
76
89
|
el.media = [...media];
|
|
77
|
-
el.action = "/
|
|
90
|
+
el.action = "/compose";
|
|
78
91
|
Object.assign(el, overrides);
|
|
79
92
|
document.body.appendChild(el);
|
|
80
93
|
await el.updateComplete;
|
|
@@ -119,21 +132,28 @@ describe("JantPostForm", () => {
|
|
|
119
132
|
titleInput.value = "Sample Post";
|
|
120
133
|
titleInput.dispatchEvent(new Event("input", { bubbles: true }));
|
|
121
134
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
135
|
+
// Set body via Tiptap JSON state (Tiptap editor may not init in happy-dom)
|
|
136
|
+
el._bodyJson = {
|
|
137
|
+
type: "doc",
|
|
138
|
+
content: [
|
|
139
|
+
{ type: "paragraph", content: [{ type: "text", text: "Hello world" }] },
|
|
140
|
+
],
|
|
141
|
+
};
|
|
142
|
+
el._body = JSON.stringify(el._bodyJson);
|
|
143
|
+
|
|
144
|
+
// Set visibility to "unlisted" via the select dropdown
|
|
145
|
+
const visibilitySelect =
|
|
146
|
+
el.querySelectorAll<HTMLSelectElement>("select.select")[2]; // [0]=format, [1]=status, [2]=visibility
|
|
147
|
+
expect(visibilitySelect).not.toBeNull();
|
|
148
|
+
if (!visibilitySelect) throw new Error("Visibility select not found");
|
|
149
|
+
visibilitySelect.value = "unlisted";
|
|
150
|
+
visibilitySelect.dispatchEvent(new Event("change", { bubbles: true }));
|
|
128
151
|
|
|
129
152
|
const checkboxList =
|
|
130
153
|
el.querySelectorAll<HTMLInputElement>("input.checkbox");
|
|
131
154
|
expect(checkboxList.length).toBeGreaterThan(0);
|
|
132
|
-
const checkbox = checkboxList[0];
|
|
133
|
-
checkbox.checked = true;
|
|
134
|
-
checkbox.dispatchEvent(new Event("change", { bubbles: true }));
|
|
135
155
|
|
|
136
|
-
const collectionCheckbox = checkboxList.item(
|
|
156
|
+
const collectionCheckbox = checkboxList.item(1);
|
|
137
157
|
expect(collectionCheckbox).not.toBeNull();
|
|
138
158
|
if (!collectionCheckbox) throw new Error("Collection checkbox missing");
|
|
139
159
|
collectionCheckbox.checked = true;
|
|
@@ -152,10 +172,10 @@ describe("JantPostForm", () => {
|
|
|
152
172
|
|
|
153
173
|
expect(detail).not.toBeNull();
|
|
154
174
|
const d = detail as unknown as PostSubmitDetail;
|
|
155
|
-
expect(d.endpoint).toBe("/
|
|
175
|
+
expect(d.endpoint).toBe("/compose");
|
|
156
176
|
expect(d.data.title).toBe("Sample Post");
|
|
157
|
-
expect(d.data.body).
|
|
158
|
-
expect(d.data.
|
|
177
|
+
expect(d.data.body).toContain("Hello world");
|
|
178
|
+
expect(d.data.visibility).toBe("unlisted");
|
|
159
179
|
expect(d.data.collectionIds).toEqual([collections[0].id]);
|
|
160
180
|
expect(d.data.mediaIds).toEqual(["m1"]);
|
|
161
181
|
});
|
|
@@ -179,7 +179,7 @@ describe("JantSettingsAvatar", () => {
|
|
|
179
179
|
|
|
180
180
|
expect(detail).not.toBeNull();
|
|
181
181
|
const d = detail as unknown as SettingsSaveDetail;
|
|
182
|
-
expect(d.endpoint).toBe("/
|
|
182
|
+
expect(d.endpoint).toBe("/settings/avatar/display");
|
|
183
183
|
expect(d.section).toBe("avatar-display");
|
|
184
184
|
expect(d.data.showHeaderAvatar).toBe("true");
|
|
185
185
|
});
|
|
@@ -201,7 +201,7 @@ describe("JantSettingsAvatar", () => {
|
|
|
201
201
|
|
|
202
202
|
expect(detail).not.toBeNull();
|
|
203
203
|
const d = detail as unknown as AvatarRemoveDetail;
|
|
204
|
-
expect(d.endpoint).toBe("/
|
|
204
|
+
expect(d.endpoint).toBe("/settings/avatar/remove");
|
|
205
205
|
});
|
|
206
206
|
|
|
207
207
|
it("saved() resets dirty state", async () => {
|
|
@@ -188,7 +188,7 @@ describe("JantSettingsGeneral", () => {
|
|
|
188
188
|
|
|
189
189
|
expect(detail).not.toBeNull();
|
|
190
190
|
const d = detail as unknown as SettingsSaveDetail;
|
|
191
|
-
expect(d.endpoint).toBe("/
|
|
191
|
+
expect(d.endpoint).toBe("/settings/general");
|
|
192
192
|
expect(d.section).toBe("general");
|
|
193
193
|
expect(d.data.siteName).toBe("New Name");
|
|
194
194
|
});
|
|
@@ -255,7 +255,7 @@ describe("JantSettingsGeneral", () => {
|
|
|
255
255
|
|
|
256
256
|
expect(detail).not.toBeNull();
|
|
257
257
|
const d = detail as unknown as SettingsSaveDetail;
|
|
258
|
-
expect(d.endpoint).toBe("/
|
|
258
|
+
expect(d.endpoint).toBe("/settings/general");
|
|
259
259
|
expect(d.section).toBe("general");
|
|
260
260
|
expect(d.data.siteFooter).toBe("New footer");
|
|
261
261
|
});
|
|
@@ -286,7 +286,7 @@ describe("JantSettingsGeneral", () => {
|
|
|
286
286
|
|
|
287
287
|
expect(detail).not.toBeNull();
|
|
288
288
|
const d = detail as unknown as SettingsSaveDetail;
|
|
289
|
-
expect(d.endpoint).toBe("/
|
|
289
|
+
expect(d.endpoint).toBe("/settings/general/seo");
|
|
290
290
|
expect(d.section).toBe("seo");
|
|
291
291
|
});
|
|
292
292
|
|