@nextsparkjs/core 0.1.0-beta.187 → 0.1.0-beta.189
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/dist/components/api/keys/ApiKeyDisplay.js +19 -19
- package/dist/components/api/keys/CreateApiKeyDialog.js +21 -21
- package/dist/components/app/layouts/PublicNavbar.d.ts.map +1 -1
- package/dist/components/app/layouts/PublicNavbar.js +34 -16
- package/dist/components/app/misc/ThemeToggle.d.ts.map +1 -1
- package/dist/components/app/misc/ThemeToggle.js +3 -4
- package/dist/components/auth/SessionCookieRefresher.d.ts +5 -0
- package/dist/components/auth/SessionCookieRefresher.d.ts.map +1 -1
- package/dist/components/auth/SessionCookieRefresher.js +7 -1
- package/dist/components/auth/forms/LoginForm.d.ts.map +1 -1
- package/dist/components/auth/forms/LoginForm.js +49 -12
- package/dist/components/auth/forms/SignupForm.d.ts.map +1 -1
- package/dist/components/auth/forms/SignupForm.js +4 -3
- package/dist/components/dashboard/block-editor/block-settings-panel.js +1 -1
- package/dist/components/dashboard/block-editor/floating-block-toolbar.js +1 -1
- package/dist/components/dashboard/block-editor/sortable-block.js +1 -1
- package/dist/components/dashboard/layouts/Sidebar.d.ts.map +1 -1
- package/dist/components/dashboard/layouts/Sidebar.js +8 -6
- package/dist/components/dashboard/layouts/TopNavbar.d.ts.map +1 -1
- package/dist/components/dashboard/layouts/TopNavbar.js +51 -54
- package/dist/components/dashboard/misc/NotificationsDropdown.d.ts.map +1 -1
- package/dist/components/dashboard/misc/NotificationsDropdown.js +17 -15
- package/dist/components/dashboard/misc/SearchDropdown.d.ts.map +1 -1
- package/dist/components/dashboard/misc/SearchDropdown.js +19 -22
- package/dist/components/dashboard/mobile/MobileBottomNav.js +1 -1
- package/dist/components/dashboard/mobile/MobileTopBar.d.ts +10 -1
- package/dist/components/dashboard/mobile/MobileTopBar.d.ts.map +1 -1
- package/dist/components/dashboard/mobile/MobileTopBar.js +4 -3
- package/dist/components/dashboard/navigation/DynamicNavigation.js +5 -5
- package/dist/components/devtools/BlockDetailViewer.js +1 -1
- package/dist/components/devtools/BlocksViewer.js +1 -1
- package/dist/components/entities/EntityChildManager.js +5 -5
- package/dist/components/entities/EntityDetailPage.d.ts.map +1 -1
- package/dist/components/entities/EntityDetailPage.js +16 -15
- package/dist/components/entities/EntityFieldRenderer.d.ts.map +1 -1
- package/dist/components/entities/EntityFieldRenderer.js +12 -7
- package/dist/components/entities/EntityPageHeader.js +5 -5
- package/dist/components/entities/ErrorBoundary.d.ts.map +1 -1
- package/dist/components/entities/ErrorBoundary.js +20 -21
- package/dist/components/entities/wrappers/EntityDetailWrapper.js +5 -5
- package/dist/components/entities/wrappers/EntityFormWrapper.js +2 -2
- package/dist/components/entities/wrappers/EntityListWrapper.js +3 -3
- package/dist/components/permissions/NoPermission.js +10 -10
- package/dist/components/public/pageBuilder/PageRenderer.d.ts.map +1 -1
- package/dist/components/public/pageBuilder/PageRenderer.js +2 -1
- package/dist/components/settings/SettingsPageSkeleton.js +4 -4
- package/dist/components/settings/layouts/SettingsSidebar.js +6 -6
- package/dist/components/shared/MultiSelectFilter.d.ts +3 -1
- package/dist/components/shared/MultiSelectFilter.d.ts.map +1 -1
- package/dist/components/shared/MultiSelectFilter.js +7 -3
- package/dist/components/shared/SearchInput.d.ts +2 -0
- package/dist/components/shared/SearchInput.d.ts.map +1 -1
- package/dist/components/shared/SearchInput.js +64 -6
- package/dist/components/ui/address-input.js +18 -18
- package/dist/components/ui/audio-upload.js +9 -9
- package/dist/components/ui/combobox.d.ts.map +1 -1
- package/dist/components/ui/combobox.js +4 -4
- package/dist/components/ui/country-select.d.ts.map +1 -1
- package/dist/components/ui/country-select.js +3 -3
- package/dist/components/ui/currency-select.d.ts.map +1 -1
- package/dist/components/ui/currency-select.js +3 -3
- package/dist/components/ui/dynamic-icon.d.ts.map +1 -1
- package/dist/components/ui/dynamic-icon.js +3 -2
- package/dist/components/ui/file-upload.js +7 -7
- package/dist/components/ui/image-upload.js +8 -8
- package/dist/components/ui/multi-select.d.ts +2 -1
- package/dist/components/ui/multi-select.d.ts.map +1 -1
- package/dist/components/ui/multi-select.js +4 -3
- package/dist/components/ui/phone-input.d.ts.map +1 -1
- package/dist/components/ui/phone-input.js +3 -3
- package/dist/components/ui/relation-display.js +1 -1
- package/dist/components/ui/simple-relation-select.d.ts +2 -1
- package/dist/components/ui/simple-relation-select.d.ts.map +1 -1
- package/dist/components/ui/simple-relation-select.js +7 -6
- package/dist/components/ui/tags-input.d.ts.map +1 -1
- package/dist/components/ui/tags-input.js +1 -1
- package/dist/components/ui/timezone-select.d.ts.map +1 -1
- package/dist/components/ui/timezone-select.js +3 -3
- package/dist/components/ui/user-display.js +4 -4
- package/dist/components/ui/user-select.d.ts.map +1 -1
- package/dist/components/ui/user-select.js +9 -9
- package/dist/components/ui/video-upload.js +9 -9
- package/dist/contexts/SubscriptionContext.d.ts.map +1 -1
- package/dist/contexts/SubscriptionContext.js +5 -1
- package/dist/contexts/TeamContext.d.ts.map +1 -1
- package/dist/contexts/TeamContext.js +83 -26
- package/dist/emails/otp-verification.d.ts.map +1 -1
- package/dist/emails/otp-verification.js +3 -2
- package/dist/hooks/useAccountPreferencesSync.d.ts +13 -0
- package/dist/hooks/useAccountPreferencesSync.d.ts.map +1 -0
- package/dist/hooks/useAccountPreferencesSync.js +95 -0
- package/dist/hooks/useAuth.d.ts +202 -15
- package/dist/hooks/useAuth.d.ts.map +1 -1
- package/dist/hooks/useAuth.js +49 -13
- package/dist/hooks/useEntityConfig.js +2 -2
- package/dist/hooks/useEntitySearch.js +10 -10
- package/dist/hooks/useNotifications.js +12 -12
- package/dist/hooks/usePrefetch.d.ts.map +1 -1
- package/dist/hooks/usePrefetch.js +6 -2
- package/dist/hooks/useSearch.js +15 -15
- package/dist/hooks/useSessionCookieRefresh.d.ts +18 -1
- package/dist/hooks/useSessionCookieRefresh.d.ts.map +1 -1
- package/dist/hooks/useSessionCookieRefresh.js +17 -4
- package/dist/hooks/useSessionHint.d.ts +12 -0
- package/dist/hooks/useSessionHint.d.ts.map +1 -0
- package/dist/hooks/useSessionHint.js +15 -0
- package/dist/hooks/useTranslationPreload.js +6 -6
- package/dist/i18n.d.ts +13 -0
- package/dist/i18n.d.ts.map +1 -1
- package/dist/i18n.js +2 -27
- package/dist/lib/actions/entity.actions.d.ts.map +1 -1
- package/dist/lib/actions/entity.actions.js +3 -2
- package/dist/lib/api/auth/dual-auth.d.ts +4 -1
- package/dist/lib/api/auth/dual-auth.d.ts.map +1 -1
- package/dist/lib/api/auth/dual-auth.js +5 -16
- package/dist/lib/api/entities.js +33 -33
- package/dist/lib/api/keys.d.ts +27 -27
- package/dist/lib/api/keys.js +27 -27
- package/dist/lib/auth/callback-url.d.ts +11 -0
- package/dist/lib/auth/callback-url.d.ts.map +1 -0
- package/dist/lib/auth/callback-url.js +14 -0
- package/dist/lib/auth/otp-config.d.ts +55 -0
- package/dist/lib/auth/otp-config.d.ts.map +1 -0
- package/dist/lib/auth/otp-config.js +48 -0
- package/dist/lib/auth/registration-helpers.d.ts.map +1 -1
- package/dist/lib/auth/registration-helpers.js +3 -1
- package/dist/lib/auth/session-hint.d.ts +31 -0
- package/dist/lib/auth/session-hint.d.ts.map +1 -0
- package/dist/lib/auth/session-hint.js +37 -0
- package/dist/lib/auth.d.ts.map +1 -1
- package/dist/lib/auth.js +6 -4
- package/dist/lib/blocks/loader.d.ts +3 -11
- package/dist/lib/blocks/loader.d.ts.map +1 -1
- package/dist/lib/blocks/loader.js +1 -9
- package/dist/lib/blocks/loader.server.d.ts +18 -0
- package/dist/lib/blocks/loader.server.d.ts.map +1 -0
- package/dist/lib/blocks/loader.server.js +11 -0
- package/dist/lib/blocks/sanitize-html.d.ts +31 -0
- package/dist/lib/blocks/sanitize-html.d.ts.map +1 -0
- package/dist/lib/blocks/sanitize-html.js +60 -0
- package/dist/lib/config/config-sync.d.ts +1 -0
- package/dist/lib/config/config-sync.d.ts.map +1 -1
- package/dist/lib/config/config-sync.js +4 -1
- package/dist/lib/config/types.d.ts +48 -0
- package/dist/lib/config/types.d.ts.map +1 -1
- package/dist/lib/email/types.d.ts +6 -0
- package/dist/lib/email/types.d.ts.map +1 -1
- package/dist/lib/entities/serialization.d.ts.map +1 -1
- package/dist/lib/entities/serialization.js +3 -6
- package/dist/lib/icons.d.ts +12 -0
- package/dist/lib/icons.d.ts.map +1 -0
- package/dist/lib/icons.js +30 -0
- package/dist/lib/locale.d.ts +25 -1
- package/dist/lib/locale.d.ts.map +1 -1
- package/dist/lib/locale.js +49 -35
- package/dist/lib/mcp/engine.js +1 -1
- package/dist/lib/mcp/errors.js +17 -17
- package/dist/lib/mcp/schema-builder.js +16 -16
- package/dist/lib/mcp/tool-generator.js +18 -18
- package/dist/lib/search-highlighting.d.ts +7 -0
- package/dist/lib/search-highlighting.d.ts.map +1 -1
- package/dist/lib/search-highlighting.js +6 -2
- package/dist/lib/selectors/core-selectors.d.ts +2 -0
- package/dist/lib/selectors/core-selectors.d.ts.map +1 -1
- package/dist/lib/selectors/domains/auth.selectors.d.ts +1 -0
- package/dist/lib/selectors/domains/auth.selectors.d.ts.map +1 -1
- package/dist/lib/selectors/domains/auth.selectors.js +1 -0
- package/dist/lib/selectors/domains/entities.selectors.d.ts +2 -0
- package/dist/lib/selectors/domains/entities.selectors.d.ts.map +1 -1
- package/dist/lib/selectors/domains/entities.selectors.js +2 -0
- package/dist/lib/selectors/selectors.d.ts +4 -0
- package/dist/lib/selectors/selectors.d.ts.map +1 -1
- package/dist/lib/services/block.service.js +1 -1
- package/dist/lib/teams/active-team-cookie.d.ts +24 -0
- package/dist/lib/teams/active-team-cookie.d.ts.map +1 -0
- package/dist/lib/teams/active-team-cookie.js +17 -0
- package/dist/lib/teams/dashboard-team.d.ts +20 -0
- package/dist/lib/teams/dashboard-team.d.ts.map +1 -0
- package/dist/lib/teams/dashboard-team.js +38 -0
- package/dist/lib/teams/schema.d.ts.map +1 -1
- package/dist/lib/teams/schema.js +1 -1
- package/dist/lib/template-resolver.d.ts.map +1 -1
- package/dist/lib/template-resolver.js +0 -1
- package/dist/lib/theme/get-default-theme-mode.d.ts +7 -4
- package/dist/lib/theme/get-default-theme-mode.d.ts.map +1 -1
- package/dist/lib/theme/get-default-theme-mode.js +2 -44
- package/dist/messages/de/auth.json +4 -2
- package/dist/messages/de/common.json +83 -3
- package/dist/messages/de/email.json +1 -1
- package/dist/messages/de/index.d.ts +87 -0
- package/dist/messages/de/index.d.ts.map +1 -1
- package/dist/messages/de/settings.json +5 -0
- package/dist/messages/en/auth.json +4 -2
- package/dist/messages/en/common.json +83 -3
- package/dist/messages/en/email.json +1 -1
- package/dist/messages/en/index.d.ts +86 -0
- package/dist/messages/en/index.d.ts.map +1 -1
- package/dist/messages/en/settings.json +4 -0
- package/dist/messages/es/auth.json +4 -2
- package/dist/messages/es/common.json +83 -3
- package/dist/messages/es/email.json +1 -1
- package/dist/messages/es/index.d.ts +86 -0
- package/dist/messages/es/index.d.ts.map +1 -1
- package/dist/messages/es/settings.json +4 -0
- package/dist/messages/fr/auth.json +4 -2
- package/dist/messages/fr/common.json +83 -3
- package/dist/messages/fr/email.json +1 -1
- package/dist/messages/fr/index.d.ts +87 -0
- package/dist/messages/fr/index.d.ts.map +1 -1
- package/dist/messages/fr/settings.json +5 -0
- package/dist/messages/it/auth.json +4 -2
- package/dist/messages/it/common.json +83 -3
- package/dist/messages/it/email.json +1 -1
- package/dist/messages/it/index.d.ts +87 -0
- package/dist/messages/it/index.d.ts.map +1 -1
- package/dist/messages/it/settings.json +5 -0
- package/dist/messages/pt/auth.json +4 -2
- package/dist/messages/pt/common.json +83 -3
- package/dist/messages/pt/email.json +1 -1
- package/dist/messages/pt/index.d.ts +87 -0
- package/dist/messages/pt/index.d.ts.map +1 -1
- package/dist/messages/pt/settings.json +5 -0
- package/dist/nextspark-registries.d.ts +54 -0
- package/dist/providers/DashboardProviders.d.ts +13 -10
- package/dist/providers/DashboardProviders.d.ts.map +1 -1
- package/dist/providers/DashboardProviders.js +7 -1
- package/dist/templates/app/(auth)/forgot-password/page.tsx +2 -2
- package/dist/templates/app/(auth)/reset-password/page.tsx +6 -6
- package/dist/templates/app/403/page.tsx +6 -6
- package/dist/templates/app/api/v1/teams/switch/route.ts +24 -5
- package/dist/templates/app/dashboard/(main)/[entity]/layout.tsx +9 -7
- package/dist/templates/app/dashboard/(main)/layout.tsx +4 -3
- package/dist/templates/app/dashboard/settings/api-keys/page.tsx +36 -34
- package/dist/templates/app/dashboard/settings/profile/page.tsx +7 -6
- package/dist/templates/app/dashboard/settings/security/page.tsx +5 -4
- package/dist/templates/app/layout.ppr.tsx +8 -8
- package/dist/templates/app/layout.tsx +12 -17
- package/dist/templates/blocks/cta-section/component.tsx +5 -2
- package/dist/templates/blocks/cta-section/config.ts +3 -2
- package/dist/templates/blocks/cta-section/fields.ts +2 -2
- package/dist/templates/blocks/cta-section/schema.ts +2 -2
- package/dist/templates/blocks/features-grid/component.tsx +10 -2
- package/dist/templates/blocks/features-grid/config.ts +3 -2
- package/dist/templates/blocks/features-grid/fields.ts +2 -2
- package/dist/templates/blocks/features-grid/schema.ts +2 -2
- package/dist/templates/blocks/hero/component.tsx +6 -3
- package/dist/templates/blocks/hero/config.ts +3 -2
- package/dist/templates/blocks/hero/fields.ts +2 -2
- package/dist/templates/blocks/hero/schema.ts +2 -2
- package/dist/templates/blocks/testimonials/component.tsx +6 -3
- package/dist/templates/blocks/testimonials/config.ts +3 -2
- package/dist/templates/blocks/testimonials/fields.ts +2 -2
- package/dist/templates/blocks/testimonials/schema.ts +2 -2
- package/dist/templates/blocks/text-content/component.tsx +7 -3
- package/dist/templates/blocks/text-content/config.ts +3 -2
- package/dist/templates/blocks/text-content/fields.ts +2 -2
- package/dist/templates/blocks/text-content/schema.ts +2 -2
- package/dist/templates/contents/themes/starter/blocks/cta-section/component.tsx +102 -0
- package/dist/templates/contents/themes/starter/blocks/cta-section/config.ts +11 -0
- package/dist/templates/contents/themes/starter/blocks/cta-section/fields.ts +89 -0
- package/dist/templates/contents/themes/starter/blocks/cta-section/index.ts +6 -0
- package/dist/templates/contents/themes/starter/blocks/cta-section/schema.ts +32 -0
- package/dist/templates/contents/themes/starter/blocks/cta-section/thumbnail.png +0 -0
- package/dist/templates/contents/themes/starter/blocks/features-grid/component.tsx +119 -0
- package/dist/templates/contents/themes/starter/blocks/features-grid/config.ts +11 -0
- package/dist/templates/contents/themes/starter/blocks/features-grid/fields.ts +97 -0
- package/dist/templates/contents/themes/starter/blocks/features-grid/index.ts +6 -0
- package/dist/templates/contents/themes/starter/blocks/features-grid/schema.ts +40 -0
- package/dist/templates/contents/themes/starter/blocks/features-grid/thumbnail.png +0 -0
- package/dist/templates/contents/themes/starter/blocks/hero/component.tsx +105 -0
- package/dist/templates/contents/themes/starter/blocks/hero/config.ts +11 -0
- package/dist/templates/contents/themes/starter/blocks/hero/fields.ts +60 -0
- package/dist/templates/contents/themes/starter/blocks/hero/index.ts +6 -0
- package/dist/templates/contents/themes/starter/blocks/hero/schema.ts +33 -0
- package/dist/templates/contents/themes/starter/blocks/hero/thumbnail.png +0 -0
- package/dist/templates/contents/themes/starter/blocks/testimonials/component.tsx +116 -0
- package/dist/templates/contents/themes/starter/blocks/testimonials/config.ts +11 -0
- package/dist/templates/contents/themes/starter/blocks/testimonials/fields.ts +105 -0
- package/dist/templates/contents/themes/starter/blocks/testimonials/index.ts +6 -0
- package/dist/templates/contents/themes/starter/blocks/testimonials/schema.ts +41 -0
- package/dist/templates/contents/themes/starter/blocks/testimonials/thumbnail.png +0 -0
- package/dist/templates/contents/themes/starter/blocks/text-content/component.tsx +100 -0
- package/dist/templates/contents/themes/starter/blocks/text-content/config.ts +11 -0
- package/dist/templates/contents/themes/starter/blocks/text-content/fields.ts +88 -0
- package/dist/templates/contents/themes/starter/blocks/text-content/index.ts +6 -0
- package/dist/templates/contents/themes/starter/blocks/text-content/schema.ts +30 -0
- package/dist/templates/contents/themes/starter/blocks/text-content/thumbnail.png +0 -0
- package/dist/templates/contents/themes/starter/config/app.config.ts +8 -0
- package/dist/templates/contents/themes/starter/entities/tasks/tasks.config.ts +7 -0
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/_utils/devtools/access.cy.ts +9 -1
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/api/entities/tasks/TaskAPIController.js +2 -2
- package/dist/templates/contents/themes/starter/tests/cypress/e2e/uat/entities/tasks/tasks-crud.cy.ts +45 -38
- package/dist/templates/contents/themes/starter/tests/cypress/fixtures/entities.json +16 -0
- package/dist/templates/contents/themes/starter/tests/cypress/src/components/DevKeyringPOM.ts +3 -1
- package/dist/templates/contents/themes/starter/tests/cypress/src/core/BlockEditorBasePOM.ts +3 -3
- package/dist/templates/contents/themes/starter/tests/cypress/src/entities/PagesPOM.ts +137 -0
- package/dist/templates/contents/themes/starter/tests/cypress/src/entities/index.ts +2 -0
- package/dist/templates/contents/themes/starter/tests/cypress/src/index.ts +1 -0
- package/dist/templates/contents/themes/starter/tests/cypress/src/session-helpers.ts +42 -11
- package/dist/templates/contents/themes/starter/tests/cypress/support/commands.ts +29 -18
- package/dist/templates/features/blog/blocks/post-content/component.tsx +5 -1
- package/dist/templates/features/blog/blocks/post-content/schema.ts +1 -1
- package/dist/templates/features/pages/blocks/hero/component.tsx +3 -0
- package/dist/templates/features/pages/blocks/hero/schema.ts +1 -1
- package/dist/templates/proxy.ts +138 -53
- package/dist/types/blocks.d.ts.map +1 -1
- package/dist/types/blocks.js +1 -1
- package/dist/types/task.types.d.ts +1 -1
- package/dist/types/task.types.js +7 -7
- package/dist/utils/dev/TranslationDebugger.js +2 -2
- package/package.json +14 -5
- package/scripts/build/registry/__tests__/block-registry.test.mjs +73 -0
- package/scripts/build/registry/__tests__/icons-discovery.test.mjs +130 -0
- package/scripts/build/registry/__tests__/identifier.test.mjs +65 -0
- package/scripts/build/registry/__tests__/page-generator.test.mjs +430 -0
- package/scripts/build/registry/__tests__/scheduled-actions-registry.test.mjs +41 -0
- package/scripts/build/registry/__tests__/template-registry.test.mjs +89 -0
- package/scripts/build/registry/discovery/icons.mjs +275 -0
- package/scripts/build/registry/discovery/index.mjs +1 -0
- package/scripts/build/registry/generators/block-registry.mjs +203 -55
- package/scripts/build/registry/generators/feature-registry.mjs +9 -2
- package/scripts/build/registry/generators/icon-registry.mjs +56 -0
- package/scripts/build/registry/generators/identifier.mjs +28 -0
- package/scripts/build/registry/generators/index.mjs +1 -0
- package/scripts/build/registry/generators/plugin-registry.mjs +4 -3
- package/scripts/build/registry/generators/scheduled-actions-registry.mjs +4 -2
- package/scripts/build/registry/generators/template-registry.mjs +49 -41
- package/scripts/build/registry/generators/theme-registry.mjs +6 -7
- package/scripts/build/registry/post-build/page-generator.mjs +380 -59
- package/scripts/build/registry.mjs +9 -1
- package/templates/app/(auth)/forgot-password/page.tsx +2 -2
- package/templates/app/(auth)/reset-password/page.tsx +6 -6
- package/templates/app/403/page.tsx +6 -6
- package/templates/app/api/v1/teams/switch/route.ts +24 -5
- package/templates/app/dashboard/(main)/[entity]/layout.tsx +9 -7
- package/templates/app/dashboard/(main)/layout.tsx +4 -3
- package/templates/app/dashboard/settings/api-keys/page.tsx +36 -34
- package/templates/app/dashboard/settings/profile/page.tsx +7 -6
- package/templates/app/dashboard/settings/security/page.tsx +5 -4
- package/templates/app/layout.ppr.tsx +8 -8
- package/templates/app/layout.tsx +12 -17
- package/templates/blocks/cta-section/component.tsx +5 -2
- package/templates/blocks/cta-section/config.ts +3 -2
- package/templates/blocks/cta-section/fields.ts +2 -2
- package/templates/blocks/cta-section/schema.ts +2 -2
- package/templates/blocks/features-grid/component.tsx +10 -2
- package/templates/blocks/features-grid/config.ts +3 -2
- package/templates/blocks/features-grid/fields.ts +2 -2
- package/templates/blocks/features-grid/schema.ts +2 -2
- package/templates/blocks/hero/component.tsx +6 -3
- package/templates/blocks/hero/config.ts +3 -2
- package/templates/blocks/hero/fields.ts +2 -2
- package/templates/blocks/hero/schema.ts +2 -2
- package/templates/blocks/testimonials/component.tsx +6 -3
- package/templates/blocks/testimonials/config.ts +3 -2
- package/templates/blocks/testimonials/fields.ts +2 -2
- package/templates/blocks/testimonials/schema.ts +2 -2
- package/templates/blocks/text-content/component.tsx +7 -3
- package/templates/blocks/text-content/config.ts +3 -2
- package/templates/blocks/text-content/fields.ts +2 -2
- package/templates/blocks/text-content/schema.ts +2 -2
- package/templates/contents/themes/starter/blocks/cta-section/component.tsx +102 -0
- package/templates/contents/themes/starter/blocks/cta-section/config.ts +11 -0
- package/templates/contents/themes/starter/blocks/cta-section/fields.ts +89 -0
- package/templates/contents/themes/starter/blocks/cta-section/index.ts +6 -0
- package/templates/contents/themes/starter/blocks/cta-section/schema.ts +32 -0
- package/templates/contents/themes/starter/blocks/cta-section/thumbnail.png +0 -0
- package/templates/contents/themes/starter/blocks/features-grid/component.tsx +119 -0
- package/templates/contents/themes/starter/blocks/features-grid/config.ts +11 -0
- package/templates/contents/themes/starter/blocks/features-grid/fields.ts +97 -0
- package/templates/contents/themes/starter/blocks/features-grid/index.ts +6 -0
- package/templates/contents/themes/starter/blocks/features-grid/schema.ts +40 -0
- package/templates/contents/themes/starter/blocks/features-grid/thumbnail.png +0 -0
- package/templates/contents/themes/starter/blocks/hero/component.tsx +105 -0
- package/templates/contents/themes/starter/blocks/hero/config.ts +11 -0
- package/templates/contents/themes/starter/blocks/hero/fields.ts +60 -0
- package/templates/contents/themes/starter/blocks/hero/index.ts +6 -0
- package/templates/contents/themes/starter/blocks/hero/schema.ts +33 -0
- package/templates/contents/themes/starter/blocks/hero/thumbnail.png +0 -0
- package/templates/contents/themes/starter/blocks/testimonials/component.tsx +116 -0
- package/templates/contents/themes/starter/blocks/testimonials/config.ts +11 -0
- package/templates/contents/themes/starter/blocks/testimonials/fields.ts +105 -0
- package/templates/contents/themes/starter/blocks/testimonials/index.ts +6 -0
- package/templates/contents/themes/starter/blocks/testimonials/schema.ts +41 -0
- package/templates/contents/themes/starter/blocks/testimonials/thumbnail.png +0 -0
- package/templates/contents/themes/starter/blocks/text-content/component.tsx +100 -0
- package/templates/contents/themes/starter/blocks/text-content/config.ts +11 -0
- package/templates/contents/themes/starter/blocks/text-content/fields.ts +88 -0
- package/templates/contents/themes/starter/blocks/text-content/index.ts +6 -0
- package/templates/contents/themes/starter/blocks/text-content/schema.ts +30 -0
- package/templates/contents/themes/starter/blocks/text-content/thumbnail.png +0 -0
- package/templates/contents/themes/starter/config/app.config.ts +8 -0
- package/templates/contents/themes/starter/entities/tasks/tasks.config.ts +7 -0
- package/templates/contents/themes/starter/tests/cypress/e2e/_utils/devtools/access.cy.ts +9 -1
- package/templates/contents/themes/starter/tests/cypress/e2e/api/entities/tasks/TaskAPIController.js +2 -2
- package/templates/contents/themes/starter/tests/cypress/e2e/uat/entities/tasks/tasks-crud.cy.ts +45 -38
- package/templates/contents/themes/starter/tests/cypress/fixtures/entities.json +16 -0
- package/templates/contents/themes/starter/tests/cypress/src/components/DevKeyringPOM.ts +3 -1
- package/templates/contents/themes/starter/tests/cypress/src/core/BlockEditorBasePOM.ts +3 -3
- package/templates/contents/themes/starter/tests/cypress/src/entities/PagesPOM.ts +137 -0
- package/templates/contents/themes/starter/tests/cypress/src/entities/index.ts +2 -0
- package/templates/contents/themes/starter/tests/cypress/src/index.ts +1 -0
- package/templates/contents/themes/starter/tests/cypress/src/session-helpers.ts +42 -11
- package/templates/contents/themes/starter/tests/cypress/support/commands.ts +29 -18
- package/templates/features/blog/blocks/post-content/component.tsx +5 -1
- package/templates/features/blog/blocks/post-content/schema.ts +1 -1
- package/templates/features/pages/blocks/hero/component.tsx +3 -0
- package/templates/features/pages/blocks/hero/schema.ts +1 -1
- package/templates/proxy.ts +138 -53
- package/tests/jest/__mocks__/@nextsparkjs/registries/block-registry.client.ts +9 -0
- package/tests/jest/__mocks__/@nextsparkjs/registries/block-registry.lazy.ts +5 -0
- package/tests/jest/__mocks__/@nextsparkjs/registries/icon-registry.ts +42 -0
- package/tests/jest/__mocks__/next-intl-server.js +85 -5
- package/tests/jest/__mocks__/next-server.js +32 -0
package/dist/templates/contents/themes/starter/tests/cypress/e2e/uat/entities/tasks/tasks-crud.cy.ts
CHANGED
|
@@ -38,24 +38,13 @@ describe('Tasks CRUD', { tags: ['@uat', '@tasks', '@crud'] }, () => {
|
|
|
38
38
|
})
|
|
39
39
|
|
|
40
40
|
afterEach(() => {
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
url: `/api/v1/tasks/${id}`,
|
|
49
|
-
headers: {
|
|
50
|
-
'Content-Type': 'application/json',
|
|
51
|
-
'x-team-id': teamId || ''
|
|
52
|
-
},
|
|
53
|
-
failOnStatusCode: false
|
|
54
|
-
})
|
|
55
|
-
})
|
|
56
|
-
createdTaskIds = []
|
|
57
|
-
})
|
|
58
|
-
}
|
|
41
|
+
// Through the command rather than a request built here: it resolves the
|
|
42
|
+
// team the API requires even before a dashboard visit has put it in
|
|
43
|
+
// localStorage. Sending an empty `x-team-id` gets a 400 that nothing
|
|
44
|
+
// reports, and the tasks survive into the next test, where a count of rows
|
|
45
|
+
// then measures the leftovers instead of what that test created.
|
|
46
|
+
createdTaskIds.forEach((id) => cy.deleteTask(id))
|
|
47
|
+
createdTaskIds = []
|
|
59
48
|
})
|
|
60
49
|
|
|
61
50
|
// ============================================================
|
|
@@ -75,7 +64,9 @@ describe('Tasks CRUD', { tags: ['@uat', '@tasks', '@crud'] }, () => {
|
|
|
75
64
|
tasks.fillTaskForm(taskData)
|
|
76
65
|
tasks.submitForm()
|
|
77
66
|
|
|
78
|
-
//
|
|
67
|
+
// Saving lands on the detail page, so reaching the list is a separate
|
|
68
|
+
// visit. What this test is about is the task existing and showing there.
|
|
69
|
+
tasks.visitList()
|
|
79
70
|
tasks.waitForList()
|
|
80
71
|
tasks.assertTaskInList(taskData.title)
|
|
81
72
|
})
|
|
@@ -93,6 +84,7 @@ describe('Tasks CRUD', { tags: ['@uat', '@tasks', '@crud'] }, () => {
|
|
|
93
84
|
tasks.fillTaskForm(taskData)
|
|
94
85
|
tasks.submitForm()
|
|
95
86
|
|
|
87
|
+
tasks.visitList()
|
|
96
88
|
tasks.waitForList()
|
|
97
89
|
tasks.assertTaskInList(taskData.title)
|
|
98
90
|
})
|
|
@@ -141,6 +133,9 @@ describe('Tasks CRUD', { tags: ['@uat', '@tasks', '@crud'] }, () => {
|
|
|
141
133
|
|
|
142
134
|
it('should navigate to task detail page', () => {
|
|
143
135
|
cy.then(() => {
|
|
136
|
+
tasks.visitList()
|
|
137
|
+
tasks.waitForList()
|
|
138
|
+
|
|
144
139
|
tasks.clickRow(testTaskId)
|
|
145
140
|
tasks.waitForDetail()
|
|
146
141
|
|
|
@@ -195,7 +190,10 @@ describe('Tasks CRUD', { tags: ['@uat', '@tasks', '@crud'] }, () => {
|
|
|
195
190
|
tasks.fillTextField('title', newTitle)
|
|
196
191
|
tasks.submitForm()
|
|
197
192
|
|
|
193
|
+
tasks.waitForDetail()
|
|
194
|
+
|
|
198
195
|
// Verify update
|
|
196
|
+
tasks.visitList()
|
|
199
197
|
tasks.waitForList()
|
|
200
198
|
tasks.assertTaskInList(newTitle)
|
|
201
199
|
tasks.assertTaskNotInList(originalTitle)
|
|
@@ -211,6 +209,9 @@ describe('Tasks CRUD', { tags: ['@uat', '@tasks', '@crud'] }, () => {
|
|
|
211
209
|
tasks.selectOption('status', 'done')
|
|
212
210
|
tasks.submitForm()
|
|
213
211
|
|
|
212
|
+
tasks.waitForDetail()
|
|
213
|
+
|
|
214
|
+
tasks.visitList()
|
|
214
215
|
tasks.waitForList()
|
|
215
216
|
// Task should now show as done
|
|
216
217
|
tasks.assertTaskInList(originalTitle)
|
|
@@ -226,6 +227,9 @@ describe('Tasks CRUD', { tags: ['@uat', '@tasks', '@crud'] }, () => {
|
|
|
226
227
|
tasks.selectOption('priority', 'urgent')
|
|
227
228
|
tasks.submitForm()
|
|
228
229
|
|
|
230
|
+
tasks.waitForDetail()
|
|
231
|
+
|
|
232
|
+
tasks.visitList()
|
|
229
233
|
tasks.waitForList()
|
|
230
234
|
tasks.assertTaskInList(originalTitle)
|
|
231
235
|
})
|
|
@@ -312,47 +316,49 @@ describe('Tasks CRUD', { tags: ['@uat', '@tasks', '@crud'] }, () => {
|
|
|
312
316
|
})
|
|
313
317
|
})
|
|
314
318
|
|
|
315
|
-
//
|
|
316
|
-
|
|
319
|
+
// The list, not a reload: `cy.reload()` keeps the current URL, so a filter
|
|
320
|
+
// the previous test left in the query string is still applied here.
|
|
321
|
+
tasks.visitList()
|
|
317
322
|
tasks.waitForList()
|
|
318
323
|
})
|
|
319
324
|
|
|
320
325
|
it('should filter tasks by status', () => {
|
|
321
|
-
// Filter by "todo" status
|
|
322
326
|
tasks.filterByStatus('todo')
|
|
323
327
|
|
|
324
|
-
//
|
|
325
|
-
|
|
328
|
+
// The filter travels in the URL, and waiting on that is what settles the
|
|
329
|
+
// list: asserting row by row while the table is still refetching detaches
|
|
330
|
+
// the very rows being checked.
|
|
331
|
+
cy.url().should('include', 'status=todo')
|
|
332
|
+
cy.get(tasks.selectors.rowGeneric).should('have.length.greaterThan', 0)
|
|
326
333
|
|
|
327
|
-
//
|
|
334
|
+
// A row shows the option's label, never the stored value.
|
|
328
335
|
cy.get(tasks.selectors.rowGeneric).each(($row) => {
|
|
329
|
-
cy.wrap($row).should('contain.text', '
|
|
336
|
+
cy.wrap($row).should('contain.text', 'To Do')
|
|
330
337
|
})
|
|
331
338
|
})
|
|
332
339
|
|
|
333
340
|
it('should filter tasks by priority', () => {
|
|
334
|
-
// Filter by "high" priority
|
|
335
341
|
tasks.filterByPriority('high')
|
|
336
342
|
|
|
337
|
-
|
|
338
|
-
cy.
|
|
343
|
+
cy.url().should('include', 'priority=high')
|
|
344
|
+
cy.get(tasks.selectors.rowGeneric).should('have.length.greaterThan', 0)
|
|
339
345
|
|
|
340
|
-
// Should show only high priority tasks
|
|
341
346
|
cy.get(tasks.selectors.rowGeneric).each(($row) => {
|
|
342
|
-
cy.wrap($row).should('contain.text', '
|
|
347
|
+
cy.wrap($row).should('contain.text', 'High')
|
|
343
348
|
})
|
|
344
349
|
})
|
|
345
350
|
|
|
346
351
|
it('should clear filters', () => {
|
|
347
|
-
// Apply filter
|
|
348
352
|
tasks.filterByStatus('todo')
|
|
349
|
-
|
|
353
|
+
// The filter travels in the URL, and waiting on that is what settles the
|
|
354
|
+
// list — a fixed wait counts rows mid-refetch and sees a partial table.
|
|
355
|
+
cy.url().should('include', 'status=todo')
|
|
350
356
|
|
|
351
|
-
// Clear filter
|
|
352
357
|
tasks.clearStatusFilter()
|
|
353
|
-
cy.
|
|
358
|
+
cy.url().should('not.include', 'status=')
|
|
354
359
|
|
|
355
|
-
//
|
|
360
|
+
// The three the beforeEach created: the starter seeds no tasks, so any
|
|
361
|
+
// higher number would be counting on a previous run's leftovers.
|
|
356
362
|
cy.get(tasks.selectors.rowGeneric).should('have.length.at.least', 3)
|
|
357
363
|
})
|
|
358
364
|
})
|
|
@@ -388,8 +394,9 @@ describe('Tasks CRUD', { tags: ['@uat', '@tasks', '@crud'] }, () => {
|
|
|
388
394
|
}
|
|
389
395
|
})
|
|
390
396
|
|
|
391
|
-
//
|
|
392
|
-
|
|
397
|
+
// The list, not a reload: a search or filter left in the query string by
|
|
398
|
+
// the previous test would still be applied.
|
|
399
|
+
tasks.visitList()
|
|
393
400
|
tasks.waitForList()
|
|
394
401
|
})
|
|
395
402
|
|
|
@@ -15,6 +15,22 @@
|
|
|
15
15
|
"status",
|
|
16
16
|
"priority"
|
|
17
17
|
]
|
|
18
|
+
},
|
|
19
|
+
"pages": {
|
|
20
|
+
"slug": "pages",
|
|
21
|
+
"singular": "page",
|
|
22
|
+
"plural": "Pages",
|
|
23
|
+
"tableName": "pages",
|
|
24
|
+
"fields": [
|
|
25
|
+
"title",
|
|
26
|
+
"slug",
|
|
27
|
+
"status",
|
|
28
|
+
"locale"
|
|
29
|
+
],
|
|
30
|
+
"filters": [
|
|
31
|
+
"status"
|
|
32
|
+
],
|
|
33
|
+
"source": "theme"
|
|
18
34
|
}
|
|
19
35
|
},
|
|
20
36
|
"tasks": {
|
package/dist/templates/contents/themes/starter/tests/cypress/src/components/DevKeyringPOM.ts
CHANGED
|
@@ -118,7 +118,9 @@ export class DevKeyringPOM extends BasePOM {
|
|
|
118
118
|
this.submitLogin()
|
|
119
119
|
|
|
120
120
|
// 3. Wait for login to complete
|
|
121
|
-
|
|
121
|
+
// No explicit timeout: an inline one wins over the run's configuration, so a
|
|
122
|
+
// slow dev server could not be waited out with `--config defaultCommandTimeout`.
|
|
123
|
+
cy.url().should('include', '/dashboard')
|
|
122
124
|
|
|
123
125
|
return this
|
|
124
126
|
}
|
|
@@ -58,9 +58,9 @@ export abstract class BlockEditorBasePOM extends BasePOM {
|
|
|
58
58
|
return {
|
|
59
59
|
// Editor main
|
|
60
60
|
container: cySelector('blockEditor.container'),
|
|
61
|
-
titleInput: cySelector('blockEditor.titleInput'),
|
|
62
|
-
slugInput: cySelector('blockEditor.slugInput'),
|
|
63
|
-
saveButton: cySelector('blockEditor.saveButton'),
|
|
61
|
+
titleInput: cySelector('blockEditor.header.titleInput'),
|
|
62
|
+
slugInput: cySelector('blockEditor.header.slugInput'),
|
|
63
|
+
saveButton: cySelector('blockEditor.header.saveButton'),
|
|
64
64
|
statusBadge: cySelector('blockEditor.statusBadge'),
|
|
65
65
|
leftSidebarToggle: cySelector('blockEditor.leftSidebarToggle'),
|
|
66
66
|
viewModeToggle: cySelector('blockEditor.viewModeToggle'),
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PagesPOM - Page Object Model for Pages entity (List operations)
|
|
3
|
+
*
|
|
4
|
+
* Extends DashboardEntityPOM for list page operations.
|
|
5
|
+
* For editing pages with the block editor, use PageBuilderPOM from features/.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* // List operations
|
|
9
|
+
* PagesPOM.create()
|
|
10
|
+
* .visitList()
|
|
11
|
+
* .waitForList()
|
|
12
|
+
* .search('About Us')
|
|
13
|
+
* .selectFilter('status', 'published')
|
|
14
|
+
*
|
|
15
|
+
* // For editing pages, use PageBuilderPOM
|
|
16
|
+
* import { PageBuilderPOM } from '../features/PageBuilderPOM'
|
|
17
|
+
* PageBuilderPOM.create().visitEdit(pageId).setTitle('New Title').save()
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import { DashboardEntityPOM } from '../core/DashboardEntityPOM'
|
|
21
|
+
import entitiesConfig from '../../fixtures/entities.json'
|
|
22
|
+
|
|
23
|
+
export interface PageListFilters {
|
|
24
|
+
status?: 'draft' | 'published' | 'archived'
|
|
25
|
+
locale?: 'en' | 'es'
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export class PagesPOM extends DashboardEntityPOM {
|
|
29
|
+
constructor() {
|
|
30
|
+
super(entitiesConfig.entities.pages.slug)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ============================================
|
|
34
|
+
// FACTORY METHOD
|
|
35
|
+
// ============================================
|
|
36
|
+
|
|
37
|
+
static create(): PagesPOM {
|
|
38
|
+
return new PagesPOM()
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// ============================================
|
|
42
|
+
// PAGE-SPECIFIC LIST METHODS
|
|
43
|
+
// ============================================
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Filter pages by status
|
|
47
|
+
*/
|
|
48
|
+
filterByStatus(status: 'draft' | 'published' | 'archived') {
|
|
49
|
+
return this.selectFilter('status', status)
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Apply multiple filters at once
|
|
54
|
+
*/
|
|
55
|
+
applyFilters(filters: PageListFilters) {
|
|
56
|
+
if (filters.status) {
|
|
57
|
+
this.filterByStatus(filters.status)
|
|
58
|
+
}
|
|
59
|
+
if (filters.locale) {
|
|
60
|
+
this.selectFilter('locale', filters.locale)
|
|
61
|
+
}
|
|
62
|
+
return this
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// ============================================
|
|
66
|
+
// WORKFLOW METHODS
|
|
67
|
+
// ============================================
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Navigate to create page
|
|
71
|
+
* Note: Pages use block editor, so this redirects to the editor
|
|
72
|
+
*/
|
|
73
|
+
navigateToCreate() {
|
|
74
|
+
this.clickAdd()
|
|
75
|
+
return this
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Navigate to edit page for a page
|
|
80
|
+
* Note: Pages use block editor, so this redirects to the editor
|
|
81
|
+
*/
|
|
82
|
+
navigateToEdit(id: string) {
|
|
83
|
+
this.clickRowAction('edit', id)
|
|
84
|
+
return this
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Delete page from list with API waits
|
|
89
|
+
*/
|
|
90
|
+
deletePageWithApiWait(id: string) {
|
|
91
|
+
this.visitDetailWithApiWait(id)
|
|
92
|
+
this.clickDelete()
|
|
93
|
+
this.confirmDelete()
|
|
94
|
+
this.api.waitForDelete()
|
|
95
|
+
return this
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Delete page by finding it in the list by title
|
|
100
|
+
*/
|
|
101
|
+
deletePageByTitleWithApiWait(title: string) {
|
|
102
|
+
this.clickRowByText(title)
|
|
103
|
+
this.waitForDetail()
|
|
104
|
+
this.clickDelete()
|
|
105
|
+
this.confirmDelete()
|
|
106
|
+
this.api.waitForDelete()
|
|
107
|
+
return this
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// ============================================
|
|
111
|
+
// ENTITY-SPECIFIC ASSERTIONS
|
|
112
|
+
// ============================================
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Assert page appears in list
|
|
116
|
+
*/
|
|
117
|
+
assertPageInList(title: string) {
|
|
118
|
+
return this.assertInList(title)
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Assert page does not appear in list
|
|
123
|
+
*/
|
|
124
|
+
assertPageNotInList(title: string) {
|
|
125
|
+
return this.assertNotInList(title)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Assert page has specific status badge
|
|
130
|
+
*/
|
|
131
|
+
assertPageStatus(id: string, status: string) {
|
|
132
|
+
cy.get(this.selectors.row(id)).should('contain.text', status)
|
|
133
|
+
return this
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export default PagesPOM
|
|
@@ -4,9 +4,11 @@
|
|
|
4
4
|
* Page Object Models for specific entities:
|
|
5
5
|
* - TasksPOM: Tasks CRUD operations
|
|
6
6
|
* - PatternsPOM: Patterns CRUD operations with usage tracking (core entity)
|
|
7
|
+
* - PagesPOM: Pages CRUD operations (the block editor specs build on it)
|
|
7
8
|
*
|
|
8
9
|
* Add more entity POMs as you create new entities.
|
|
9
10
|
*/
|
|
10
11
|
|
|
11
12
|
export { TasksPOM, type TaskFormData } from './TasksPOM'
|
|
12
13
|
export { PatternsPOM } from './PatternsPOM'
|
|
14
|
+
export { PagesPOM } from './PagesPOM'
|
|
@@ -39,19 +39,50 @@ const SUPERADMIN_PASSWORD = Cypress.env('SUPERADMIN_PASSWORD') || 'Pandora1234'
|
|
|
39
39
|
const TEST_PASSWORD = Cypress.env('TEST_PASSWORD') || 'Test1234'
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
43
|
-
* Teams: Everpoint Labs, Ironvale Global, Riverstone Ventures
|
|
42
|
+
* Team-role test users.
|
|
44
43
|
*
|
|
45
|
-
*
|
|
44
|
+
* The starter seeds exactly two users (core migration 090): superadmin and
|
|
45
|
+
* developer. The names below come from the default theme's richer sample data,
|
|
46
|
+
* and every one of them has to be pointed at a real user through the matching
|
|
47
|
+
* env var before the specs that use it can run.
|
|
48
|
+
*
|
|
49
|
+
* OWNER is the exception, and it matters: it is what the CRUD specs log in as,
|
|
50
|
+
* so its fallback is the user the starter actually creates — superadmin owns
|
|
51
|
+
* the initial team. Leaving it on a name with no row made the whole UAT suite
|
|
52
|
+
* fail in session setup, before a single assertion.
|
|
46
53
|
*/
|
|
47
54
|
export const DEFAULT_THEME_USERS = {
|
|
48
|
-
OWNER: Cypress.env('OWNER_EMAIL') || '
|
|
55
|
+
OWNER: Cypress.env('OWNER_EMAIL') || 'superadmin@nextspark.dev',
|
|
49
56
|
ADMIN: Cypress.env('ADMIN_EMAIL') || 'james.wilson@nextspark.dev',
|
|
50
57
|
MEMBER: Cypress.env('MEMBER_EMAIL') || 'emily.johnson@nextspark.dev',
|
|
51
58
|
EDITOR: Cypress.env('EDITOR_EMAIL') || 'diego.ramirez@nextspark.dev',
|
|
52
59
|
VIEWER: Cypress.env('VIEWER_EMAIL') || 'sarah.davis@nextspark.dev',
|
|
53
60
|
} as const
|
|
54
61
|
|
|
62
|
+
/**
|
|
63
|
+
* The password that goes with OWNER.
|
|
64
|
+
*
|
|
65
|
+
* OWNER falls back to the seeded superadmin, and that user's password is the
|
|
66
|
+
* superadmin one, not the demo-user one. A theme that points OWNER at a user of
|
|
67
|
+
* its own sets OWNER_EMAIL, and then the demo password is the right default.
|
|
68
|
+
*/
|
|
69
|
+
const OWNER_PASSWORD =
|
|
70
|
+
Cypress.env('OWNER_PASSWORD') ||
|
|
71
|
+
(Cypress.env('OWNER_EMAIL') ? TEST_PASSWORD : SUPERADMIN_PASSWORD)
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Whether a non-owner team role points at a user that exists.
|
|
75
|
+
*
|
|
76
|
+
* Only OWNER has a seeded fallback. The other four keep the default theme's
|
|
77
|
+
* names, which resolve to nothing here until the theme seeds them and sets the
|
|
78
|
+
* matching env var. A spec that needs one guards on this instead of failing in
|
|
79
|
+
* session setup, where the error is a ten-second timeout on the Dev Keyring
|
|
80
|
+
* rather than "this user does not exist".
|
|
81
|
+
*/
|
|
82
|
+
export function hasSeededTeamRoleUser(role: 'ADMIN' | 'MEMBER' | 'EDITOR' | 'VIEWER'): boolean {
|
|
83
|
+
return Boolean(Cypress.env(`${role}_EMAIL`))
|
|
84
|
+
}
|
|
85
|
+
|
|
55
86
|
/**
|
|
56
87
|
* Core System Users (from core/migrations/090_sample_data.sql)
|
|
57
88
|
* These users have special global roles, not team-based roles
|
|
@@ -164,7 +195,7 @@ function apiLogin(email: string, password: string = TEST_PASSWORD): Cypress.Chai
|
|
|
164
195
|
*/
|
|
165
196
|
export function loginAsDefaultOwner() {
|
|
166
197
|
cy.session('default-owner-session', () => {
|
|
167
|
-
apiLogin(DEFAULT_THEME_USERS.OWNER).then((apiLoginSucceeded) => {
|
|
198
|
+
apiLogin(DEFAULT_THEME_USERS.OWNER, OWNER_PASSWORD).then((apiLoginSucceeded) => {
|
|
168
199
|
// If API login succeeded, we need to visit a page before setting localStorage
|
|
169
200
|
if (apiLoginSucceeded) {
|
|
170
201
|
cy.visit('/dashboard', { timeout: 60000 })
|
|
@@ -389,22 +420,22 @@ export function getThemeUsers() {
|
|
|
389
420
|
*/
|
|
390
421
|
export const BILLING_TEAMS = {
|
|
391
422
|
FREE: {
|
|
392
|
-
teamId: 'team-personal-carlos-001',
|
|
423
|
+
teamId: Cypress.env('BILLING_FREE_TEAM_ID') || 'team-personal-carlos-001',
|
|
393
424
|
name: 'Carlos Personal',
|
|
394
425
|
planSlug: 'free',
|
|
395
|
-
owner: 'carlos.mendoza@nextspark.dev'
|
|
426
|
+
owner: Cypress.env('BILLING_FREE_OWNER') || 'carlos.mendoza@nextspark.dev'
|
|
396
427
|
},
|
|
397
428
|
PRO: {
|
|
398
|
-
teamId: 'team-everpoint-001',
|
|
429
|
+
teamId: Cypress.env('BILLING_PRO_TEAM_ID') || 'team-everpoint-001',
|
|
399
430
|
name: 'Everpoint Labs',
|
|
400
431
|
planSlug: 'pro',
|
|
401
|
-
owner: 'carlos.mendoza@nextspark.dev'
|
|
432
|
+
owner: Cypress.env('BILLING_PRO_OWNER') || 'carlos.mendoza@nextspark.dev'
|
|
402
433
|
},
|
|
403
434
|
ENTERPRISE: {
|
|
404
|
-
teamId: 'team-ironvale-002',
|
|
435
|
+
teamId: Cypress.env('BILLING_ENTERPRISE_TEAM_ID') || 'team-ironvale-002',
|
|
405
436
|
name: 'Ironvale Global',
|
|
406
437
|
planSlug: 'enterprise',
|
|
407
|
-
owner: 'ana.garcia@nextspark.dev'
|
|
438
|
+
owner: Cypress.env('BILLING_ENTERPRISE_OWNER') || 'ana.garcia@nextspark.dev'
|
|
408
439
|
}
|
|
409
440
|
} as const
|
|
410
441
|
|
|
@@ -140,18 +140,37 @@ Cypress.Commands.add('logout', () => {
|
|
|
140
140
|
})
|
|
141
141
|
|
|
142
142
|
/**
|
|
143
|
-
*
|
|
143
|
+
* The headers an entity API call needs, `x-team-id` included.
|
|
144
|
+
*
|
|
145
|
+
* The app writes `activeTeamId` into localStorage while the dashboard loads, so
|
|
146
|
+
* a command that runs before any dashboard visit — a `beforeEach` seeding data,
|
|
147
|
+
* typically — finds nothing there. Without the header the API answers 400
|
|
148
|
+
* TEAM_CONTEXT_REQUIRED, and since these requests do not fail on status the
|
|
149
|
+
* seed silently does nothing: the failure only surfaces later, as an assertion
|
|
150
|
+
* about data that was never created. Asking the API for the team is what makes
|
|
151
|
+
* the command work from any starting point.
|
|
144
152
|
*/
|
|
145
|
-
Cypress.
|
|
153
|
+
function apiHeaders(): Cypress.Chainable<Record<string, string>> {
|
|
154
|
+
const base: Record<string, string> = { 'Content-Type': 'application/json' }
|
|
155
|
+
|
|
146
156
|
return cy.window().then((win) => {
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
157
|
+
const stored = win.localStorage.getItem('activeTeamId')
|
|
158
|
+
if (stored) return cy.wrap({ ...base, 'x-team-id': stored })
|
|
159
|
+
|
|
160
|
+
return cy
|
|
161
|
+
.request({ method: 'GET', url: '/api/v1/teams', failOnStatusCode: false })
|
|
162
|
+
.then((response) => {
|
|
163
|
+
const teamId = response.body?.data?.[0]?.id
|
|
164
|
+
return cy.wrap(teamId ? { ...base, 'x-team-id': teamId } : base)
|
|
165
|
+
})
|
|
166
|
+
})
|
|
167
|
+
}
|
|
154
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Create a task via API
|
|
171
|
+
*/
|
|
172
|
+
Cypress.Commands.add('createTask', (data) => {
|
|
173
|
+
return apiHeaders().then((headers) => {
|
|
155
174
|
return cy.request({
|
|
156
175
|
method: 'POST',
|
|
157
176
|
url: '/api/v1/tasks',
|
|
@@ -171,15 +190,7 @@ Cypress.Commands.add('createTask', (data) => {
|
|
|
171
190
|
* Delete a task via API
|
|
172
191
|
*/
|
|
173
192
|
Cypress.Commands.add('deleteTask', (id: string) => {
|
|
174
|
-
return
|
|
175
|
-
const teamId = win.localStorage.getItem('activeTeamId')
|
|
176
|
-
const headers: Record<string, string> = {
|
|
177
|
-
'Content-Type': 'application/json',
|
|
178
|
-
}
|
|
179
|
-
if (teamId) {
|
|
180
|
-
headers['x-team-id'] = teamId
|
|
181
|
-
}
|
|
182
|
-
|
|
193
|
+
return apiHeaders().then((headers) => {
|
|
183
194
|
return cy.request({
|
|
184
195
|
method: 'DELETE',
|
|
185
196
|
url: `/api/v1/tasks/${id}`,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import React from 'react'
|
|
2
2
|
import { cn } from '@nextsparkjs/core/lib/utils'
|
|
3
3
|
import { buildSectionClasses } from '@nextsparkjs/core/types/blocks'
|
|
4
|
+
import { sanitizeBlockHtml } from '@nextsparkjs/core/lib/blocks/sanitize-html'
|
|
4
5
|
import { sel } from '../../lib/selectors'
|
|
5
6
|
import type { PostContentBlockProps } from './schema'
|
|
6
7
|
|
|
@@ -171,7 +172,7 @@ export function PostContentBlock({
|
|
|
171
172
|
// Em/italic
|
|
172
173
|
'prose-em:italic'
|
|
173
174
|
)}
|
|
174
|
-
dangerouslySetInnerHTML={{ __html: content }}
|
|
175
|
+
dangerouslySetInnerHTML={{ __html: sanitizeBlockHtml(content) }}
|
|
175
176
|
/>
|
|
176
177
|
|
|
177
178
|
{/* Optional Divider after content */}
|
|
@@ -195,3 +196,6 @@ export function PostContentBlock({
|
|
|
195
196
|
</section>
|
|
196
197
|
)
|
|
197
198
|
}
|
|
199
|
+
|
|
200
|
+
// The generated block registry imports this as the module's default.
|
|
201
|
+
export default PostContentBlock
|
|
@@ -41,6 +41,6 @@ export const postContentSpecificSchema = z.object({
|
|
|
41
41
|
* Complete Post Content Block Schema
|
|
42
42
|
* Note: postContentSpecificSchema.content overrides baseBlockSchema.content
|
|
43
43
|
*/
|
|
44
|
-
export const schema = baseBlockSchema.
|
|
44
|
+
export const schema = baseBlockSchema.extend(postContentSpecificSchema.shape)
|
|
45
45
|
|
|
46
46
|
export type PostContentBlockProps = z.infer<typeof schema>
|
|
@@ -27,7 +27,7 @@ export const heroSpecificSchema = z.object({
|
|
|
27
27
|
* Complete Hero Block Schema
|
|
28
28
|
* Combines base fields + hero-specific fields
|
|
29
29
|
*/
|
|
30
|
-
export const schema = baseBlockSchema.
|
|
30
|
+
export const schema = baseBlockSchema.extend(heroSpecificSchema.shape)
|
|
31
31
|
|
|
32
32
|
export type HeroBlockProps = z.infer<typeof schema>
|
|
33
33
|
|