@jasonshimmy/vite-plugin-cer-app 0.23.2 → 0.24.0
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/cli/checks/lighthouse.d.ts +26 -0
- package/dist/cli/checks/lighthouse.d.ts.map +1 -0
- package/dist/cli/checks/lighthouse.js +121 -0
- package/dist/cli/checks/lighthouse.js.map +1 -0
- package/dist/cli/checks/links.d.ts +12 -0
- package/dist/cli/checks/links.d.ts.map +1 -0
- package/dist/cli/checks/links.js +89 -0
- package/dist/cli/checks/links.js.map +1 -0
- package/dist/cli/checks/performance.d.ts +17 -0
- package/dist/cli/checks/performance.d.ts.map +1 -0
- package/dist/cli/checks/performance.js +61 -0
- package/dist/cli/checks/performance.js.map +1 -0
- package/dist/cli/commands/check.d.ts +3 -0
- package/dist/cli/commands/check.d.ts.map +1 -0
- package/dist/cli/commands/check.js +85 -0
- package/dist/cli/commands/check.js.map +1 -0
- package/dist/cli/create/index.d.ts +11 -1
- package/dist/cli/create/index.d.ts.map +1 -1
- package/dist/cli/create/index.js +135 -65
- package/dist/cli/create/index.js.map +1 -1
- package/dist/cli/create/templates/spa/package.json.tpl +5 -3
- package/dist/cli/create/templates/ssg/cer.config.ts.tpl +2 -0
- package/dist/cli/create/templates/ssg/package.json.tpl +5 -3
- package/dist/cli/create/templates/ssr/package.json.tpl +5 -3
- package/dist/cli/index.js +2 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/plugin/build-ssg.d.ts +22 -6
- package/dist/plugin/build-ssg.d.ts.map +1 -1
- package/dist/plugin/build-ssg.js +227 -17
- package/dist/plugin/build-ssg.js.map +1 -1
- package/dist/plugin/content/parser.d.ts.map +1 -1
- package/dist/plugin/content/parser.js +54 -10
- package/dist/plugin/content/parser.js.map +1 -1
- package/dist/plugin/dev-server.d.ts +4 -1
- package/dist/plugin/dev-server.d.ts.map +1 -1
- package/dist/plugin/dev-server.js.map +1 -1
- package/dist/plugin/dts-generator.d.ts.map +1 -1
- package/dist/plugin/dts-generator.js +50 -8
- package/dist/plugin/dts-generator.js.map +1 -1
- package/dist/plugin/generated-dir.d.ts +2 -0
- package/dist/plugin/generated-dir.d.ts.map +1 -1
- package/dist/plugin/generated-dir.js +17 -6
- package/dist/plugin/generated-dir.js.map +1 -1
- package/dist/plugin/html-post-process.d.ts +6 -0
- package/dist/plugin/html-post-process.d.ts.map +1 -1
- package/dist/plugin/html-post-process.js +24 -0
- package/dist/plugin/html-post-process.js.map +1 -1
- package/dist/plugin/index.d.ts.map +1 -1
- package/dist/plugin/index.js +60 -13
- package/dist/plugin/index.js.map +1 -1
- package/dist/plugin/transforms/auto-import.d.ts.map +1 -1
- package/dist/plugin/transforms/auto-import.js +7 -0
- package/dist/plugin/transforms/auto-import.js.map +1 -1
- package/dist/plugin/transforms/prune-runtime-css.d.ts +8 -0
- package/dist/plugin/transforms/prune-runtime-css.d.ts.map +1 -0
- package/dist/plugin/transforms/prune-runtime-css.js +40 -0
- package/dist/plugin/transforms/prune-runtime-css.js.map +1 -0
- package/dist/runtime/app-template.d.ts +1 -1
- package/dist/runtime/app-template.d.ts.map +1 -1
- package/dist/runtime/app-template.js +206 -36
- package/dist/runtime/app-template.js.map +1 -1
- package/dist/runtime/composables/index.d.ts +4 -0
- package/dist/runtime/composables/index.d.ts.map +1 -1
- package/dist/runtime/composables/index.js +2 -0
- package/dist/runtime/composables/index.js.map +1 -1
- package/dist/runtime/composables/use-active-headings.d.ts +24 -0
- package/dist/runtime/composables/use-active-headings.d.ts.map +1 -0
- package/dist/runtime/composables/use-active-headings.js +112 -0
- package/dist/runtime/composables/use-active-headings.js.map +1 -0
- package/dist/runtime/composables/use-content-page.d.ts +45 -0
- package/dist/runtime/composables/use-content-page.d.ts.map +1 -0
- package/dist/runtime/composables/use-content-page.js +179 -0
- package/dist/runtime/composables/use-content-page.js.map +1 -0
- package/dist/runtime/composables/use-content-search.d.ts.map +1 -1
- package/dist/runtime/composables/use-content-search.js +1 -5
- package/dist/runtime/composables/use-content-search.js.map +1 -1
- package/dist/runtime/composables/use-fetch.d.ts +2 -1
- package/dist/runtime/composables/use-fetch.d.ts.map +1 -1
- package/dist/runtime/composables/use-fetch.js +112 -43
- package/dist/runtime/composables/use-fetch.js.map +1 -1
- package/dist/runtime/composables/use-route.d.ts.map +1 -1
- package/dist/runtime/composables/use-route.js +39 -11
- package/dist/runtime/composables/use-route.js.map +1 -1
- package/dist/runtime/content/client.js +2 -2
- package/dist/runtime/content/client.js.map +1 -1
- package/dist/runtime/entry-server-template.d.ts +16 -1
- package/dist/runtime/entry-server-template.d.ts.map +1 -1
- package/dist/runtime/entry-server-template.js +120 -13
- package/dist/runtime/entry-server-template.js.map +1 -1
- package/dist/types/config.d.ts +45 -4
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/config.js.map +1 -1
- package/dist/types/middleware.d.ts +2 -2
- package/dist/types/middleware.d.ts.map +1 -1
- package/package.json +22 -19
- package/.github/copilot-instructions.md +0 -169
- package/.github/workflows/publish.yml +0 -257
- package/.nvmrc +0 -1
- package/CHANGELOG.md +0 -236
- package/CLAUDE.md +0 -113
- package/commits.txt +0 -1
- package/cypress.config.ts +0 -16
- package/docs/authentication.md +0 -285
- package/docs/cli.md +0 -324
- package/docs/components.md +0 -237
- package/docs/composables.md +0 -907
- package/docs/configuration.md +0 -696
- package/docs/content.md +0 -570
- package/docs/data-loading.md +0 -336
- package/docs/getting-started.md +0 -237
- package/docs/head-management.md +0 -212
- package/docs/i18n.md +0 -159
- package/docs/layouts.md +0 -224
- package/docs/middleware.md +0 -234
- package/docs/plugins.md +0 -170
- package/docs/rendering-modes.md +0 -377
- package/docs/routing.md +0 -485
- package/docs/server-api.md +0 -253
- package/docs/testing.md +0 -455
- package/docs/use-fetch.md +0 -183
- package/e2e/cypress/e2e/api.cy.ts +0 -123
- package/e2e/cypress/e2e/async-component.cy.ts +0 -27
- package/e2e/cypress/e2e/component-splitting.cy.ts +0 -50
- package/e2e/cypress/e2e/content.cy.ts +0 -425
- package/e2e/cypress/e2e/cookie.cy.ts +0 -85
- package/e2e/cypress/e2e/data.cy.ts +0 -158
- package/e2e/cypress/e2e/error-boundary.cy.ts +0 -88
- package/e2e/cypress/e2e/fouc.cy.ts +0 -254
- package/e2e/cypress/e2e/group-meta.cy.ts +0 -36
- package/e2e/cypress/e2e/head.cy.ts +0 -89
- package/e2e/cypress/e2e/i18n.cy.ts +0 -79
- package/e2e/cypress/e2e/interactive.cy.ts +0 -137
- package/e2e/cypress/e2e/isr-nested-runtime.cy.ts +0 -102
- package/e2e/cypress/e2e/jit-css-custom-colors.cy.ts +0 -43
- package/e2e/cypress/e2e/middleware-chain.cy.ts +0 -89
- package/e2e/cypress/e2e/middleware-status.cy.ts +0 -30
- package/e2e/cypress/e2e/middleware.cy.ts +0 -45
- package/e2e/cypress/e2e/navigate.cy.ts +0 -39
- package/e2e/cypress/e2e/observability.cy.ts +0 -77
- package/e2e/cypress/e2e/per-route-error.cy.ts +0 -42
- package/e2e/cypress/e2e/per-route-render.cy.ts +0 -70
- package/e2e/cypress/e2e/preview-hardening.cy.ts +0 -88
- package/e2e/cypress/e2e/routes.cy.ts +0 -128
- package/e2e/cypress/e2e/seo-meta.cy.ts +0 -108
- package/e2e/cypress/e2e/server-middleware.cy.ts +0 -46
- package/e2e/cypress/e2e/session-rotation.cy.ts +0 -25
- package/e2e/cypress/e2e/session.cy.ts +0 -73
- package/e2e/cypress/e2e/ssr-render-error.cy.ts +0 -68
- package/e2e/cypress/e2e/synthetic-404.cy.ts +0 -45
- package/e2e/cypress/e2e/use-page-data.cy.ts +0 -122
- package/e2e/cypress/e2e/use-state.cy.ts +0 -138
- package/e2e/cypress/support/commands.ts +0 -120
- package/e2e/cypress/support/e2e.ts +0 -10
- package/e2e/cypress/tsconfig.json +0 -14
- package/e2e/kitchen-sink/app/components/ks-badge.ts +0 -8
- package/e2e/kitchen-sink/app/composables/useKsCounter.ts +0 -9
- package/e2e/kitchen-sink/app/error.ts +0 -18
- package/e2e/kitchen-sink/app/layouts/admin.ts +0 -13
- package/e2e/kitchen-sink/app/layouts/default.ts +0 -25
- package/e2e/kitchen-sink/app/layouts/group.ts +0 -9
- package/e2e/kitchen-sink/app/layouts/minimal.ts +0 -7
- package/e2e/kitchen-sink/app/loading.ts +0 -9
- package/e2e/kitchen-sink/app/middleware/auth.ts +0 -9
- package/e2e/kitchen-sink/app/middleware/custom-log.ts +0 -4
- package/e2e/kitchen-sink/app/middleware/group-auth.ts +0 -7
- package/e2e/kitchen-sink/app/middleware/logger.ts +0 -14
- package/e2e/kitchen-sink/app/pages/(auth)/login.ts +0 -13
- package/e2e/kitchen-sink/app/pages/(auth)/protected.ts +0 -16
- package/e2e/kitchen-sink/app/pages/404.ts +0 -9
- package/e2e/kitchen-sink/app/pages/about.ts +0 -17
- package/e2e/kitchen-sink/app/pages/admin/_layout.ts +0 -1
- package/e2e/kitchen-sink/app/pages/admin/dashboard.ts +0 -11
- package/e2e/kitchen-sink/app/pages/async-component-error-test.ts +0 -18
- package/e2e/kitchen-sink/app/pages/async-component-test.ts +0 -18
- package/e2e/kitchen-sink/app/pages/blog/[slug].ts +0 -59
- package/e2e/kitchen-sink/app/pages/blog/index.ts +0 -51
- package/e2e/kitchen-sink/app/pages/content-blog.ts +0 -37
- package/e2e/kitchen-sink/app/pages/content-doc.ts +0 -42
- package/e2e/kitchen-sink/app/pages/content-fallback.ts +0 -36
- package/e2e/kitchen-sink/app/pages/content-guides.ts +0 -35
- package/e2e/kitchen-sink/app/pages/content-index.ts +0 -39
- package/e2e/kitchen-sink/app/pages/content-search.ts +0 -36
- package/e2e/kitchen-sink/app/pages/cookie-test.ts +0 -22
- package/e2e/kitchen-sink/app/pages/counter.ts +0 -17
- package/e2e/kitchen-sink/app/pages/group-auth-blocked.ts +0 -9
- package/e2e/kitchen-sink/app/pages/group-meta-test/_layout.ts +0 -6
- package/e2e/kitchen-sink/app/pages/group-meta-test/custom-mw.ts +0 -14
- package/e2e/kitchen-sink/app/pages/group-meta-test/page.ts +0 -9
- package/e2e/kitchen-sink/app/pages/group-meta-test/protected.ts +0 -8
- package/e2e/kitchen-sink/app/pages/head.ts +0 -20
- package/e2e/kitchen-sink/app/pages/i18n-test.ts +0 -14
- package/e2e/kitchen-sink/app/pages/index.ts +0 -27
- package/e2e/kitchen-sink/app/pages/isr-test.ts +0 -17
- package/e2e/kitchen-sink/app/pages/items/[id].ts +0 -20
- package/e2e/kitchen-sink/app/pages/jit-css-custom-colors-test.ts +0 -14
- package/e2e/kitchen-sink/app/pages/loader-error-test.ts +0 -13
- package/e2e/kitchen-sink/app/pages/loader-props-test.ts +0 -19
- package/e2e/kitchen-sink/app/pages/loader-response-error-test.ts +0 -13
- package/e2e/kitchen-sink/app/pages/middleware-chain-test.ts +0 -12
- package/e2e/kitchen-sink/app/pages/middleware-status-test.ts +0 -9
- package/e2e/kitchen-sink/app/pages/navigate-test.ts +0 -16
- package/e2e/kitchen-sink/app/pages/observability-test.ts +0 -25
- package/e2e/kitchen-sink/app/pages/per-route-error-test.error.ts +0 -13
- package/e2e/kitchen-sink/app/pages/per-route-error-test.ts +0 -15
- package/e2e/kitchen-sink/app/pages/plugin-dsd-test.ts +0 -10
- package/e2e/kitchen-sink/app/pages/render-error-test.ts +0 -12
- package/e2e/kitchen-sink/app/pages/render-server-test.ts +0 -12
- package/e2e/kitchen-sink/app/pages/render-spa-test.ts +0 -12
- package/e2e/kitchen-sink/app/pages/route-info.ts +0 -14
- package/e2e/kitchen-sink/app/pages/seo-test.ts +0 -23
- package/e2e/kitchen-sink/app/pages/session-rotation-test.ts +0 -25
- package/e2e/kitchen-sink/app/pages/use-state-test.ts +0 -37
- package/e2e/kitchen-sink/app/plugins/01.setup.ts +0 -7
- package/e2e/kitchen-sink/app/plugins/02.ks-plugin-components.ts +0 -27
- package/e2e/kitchen-sink/cer-auto-imports.d.ts +0 -51
- package/e2e/kitchen-sink/cer-env.d.ts +0 -35
- package/e2e/kitchen-sink/cer-tsconfig.json +0 -30
- package/e2e/kitchen-sink/cer.config.ts +0 -43
- package/e2e/kitchen-sink/content/01.guides/01.index.md +0 -8
- package/e2e/kitchen-sink/content/01.guides/02.intro.md +0 -8
- package/e2e/kitchen-sink/content/01.guides/10.advanced.md +0 -8
- package/e2e/kitchen-sink/content/blog/2026-04-01-hello.md +0 -26
- package/e2e/kitchen-sink/content/blog/2026-04-02-draft.md +0 -10
- package/e2e/kitchen-sink/content/blog/index.md +0 -8
- package/e2e/kitchen-sink/content/blog/no-frontmatter.md +0 -7
- package/e2e/kitchen-sink/content/docs/getting-started.md +0 -48
- package/e2e/kitchen-sink/content/index.md +0 -16
- package/e2e/kitchen-sink/server/api/echo.ts +0 -12
- package/e2e/kitchen-sink/server/api/health.ts +0 -3
- package/e2e/kitchen-sink/server/api/posts/[slug].ts +0 -11
- package/e2e/kitchen-sink/server/api/posts/index.ts +0 -5
- package/e2e/kitchen-sink/server/api/session.ts +0 -23
- package/e2e/kitchen-sink/server/data/posts.ts +0 -21
- package/e2e/kitchen-sink/server/middleware/01-headers.ts +0 -6
- package/e2e/kitchen-sink/server/middleware/02-status-test.ts +0 -10
- package/e2e/kitchen-sink/tsconfig.json +0 -3
- package/e2e/scripts/clean.mjs +0 -14
- package/eslint.config.ts +0 -22
- package/src/__tests__/cli/adapters/cloudflare-worker.integration.test.ts +0 -132
- package/src/__tests__/cli/adapters/cloudflare.test.ts +0 -332
- package/src/__tests__/cli/adapters/netlify-bridge.integration.test.ts +0 -139
- package/src/__tests__/cli/adapters/netlify.test.ts +0 -286
- package/src/__tests__/cli/adapters/vercel-launcher.integration.test.ts +0 -129
- package/src/__tests__/cli/adapters/vercel.test.ts +0 -263
- package/src/__tests__/cli/preview-hardening.test.ts +0 -265
- package/src/__tests__/cli/preview-isr.test.ts +0 -320
- package/src/__tests__/index.test.ts +0 -21
- package/src/__tests__/plugin/app-template.test.ts +0 -166
- package/src/__tests__/plugin/build-ssg-render.test.ts +0 -155
- package/src/__tests__/plugin/build-ssg.test.ts +0 -598
- package/src/__tests__/plugin/build-ssr.test.ts +0 -192
- package/src/__tests__/plugin/cer-app-plugin.test.ts +0 -552
- package/src/__tests__/plugin/content/emitter.test.ts +0 -117
- package/src/__tests__/plugin/content/loader.test.ts +0 -154
- package/src/__tests__/plugin/content/parser.test.ts +0 -381
- package/src/__tests__/plugin/content/path-utils.test.ts +0 -69
- package/src/__tests__/plugin/content/search.test.ts +0 -119
- package/src/__tests__/plugin/dev-server.test.ts +0 -813
- package/src/__tests__/plugin/dts-generator.test.ts +0 -394
- package/src/__tests__/plugin/entry-server-template.test.ts +0 -385
- package/src/__tests__/plugin/generated-dir.test.ts +0 -144
- package/src/__tests__/plugin/html-post-process.test.ts +0 -146
- package/src/__tests__/plugin/path-utils.test.ts +0 -411
- package/src/__tests__/plugin/resolve-config.test.ts +0 -233
- package/src/__tests__/plugin/scanner.test.ts +0 -186
- package/src/__tests__/plugin/transforms/auto-import.test.ts +0 -510
- package/src/__tests__/plugin/transforms/head-inject.test.ts +0 -178
- package/src/__tests__/plugin/virtual/composables.test.ts +0 -57
- package/src/__tests__/plugin/virtual/content-components.test.ts +0 -66
- package/src/__tests__/plugin/virtual/error.test.ts +0 -71
- package/src/__tests__/plugin/virtual/layouts.test.ts +0 -70
- package/src/__tests__/plugin/virtual/loading.test.ts +0 -72
- package/src/__tests__/plugin/virtual/middleware.test.ts +0 -83
- package/src/__tests__/plugin/virtual/plugins.test.ts +0 -129
- package/src/__tests__/plugin/virtual/routes.test.ts +0 -884
- package/src/__tests__/plugin/virtual/server-api.test.ts +0 -164
- package/src/__tests__/plugin/virtual/server-middleware.test.ts +0 -102
- package/src/__tests__/runtime/app-template.test.ts +0 -208
- package/src/__tests__/runtime/define-middleware.test.ts +0 -64
- package/src/__tests__/runtime/define-server-middleware.test.ts +0 -54
- package/src/__tests__/runtime/entry-client-template.test.ts +0 -61
- package/src/__tests__/runtime/isr-handler.test.ts +0 -338
- package/src/__tests__/runtime/oauth/handler.test.ts +0 -358
- package/src/__tests__/runtime/oauth/providers.test.ts +0 -47
- package/src/__tests__/runtime/oauth-index.test.ts +0 -43
- package/src/__tests__/runtime/use-auth.test.ts +0 -169
- package/src/__tests__/runtime/use-content-search-composable.test.ts +0 -405
- package/src/__tests__/runtime/use-content-search.test.ts +0 -163
- package/src/__tests__/runtime/use-content.test.ts +0 -226
- package/src/__tests__/runtime/use-cookie.test.ts +0 -277
- package/src/__tests__/runtime/use-fetch-component.test.ts +0 -214
- package/src/__tests__/runtime/use-fetch.test.ts +0 -377
- package/src/__tests__/runtime/use-head.test.ts +0 -311
- package/src/__tests__/runtime/use-inject-client.test.ts +0 -67
- package/src/__tests__/runtime/use-inject.test.ts +0 -66
- package/src/__tests__/runtime/use-locale.test.ts +0 -152
- package/src/__tests__/runtime/use-navigate.test.ts +0 -121
- package/src/__tests__/runtime/use-page-data.test.ts +0 -298
- package/src/__tests__/runtime/use-route.test.ts +0 -156
- package/src/__tests__/runtime/use-runtime-config.test.ts +0 -182
- package/src/__tests__/runtime/use-seo-meta.test.ts +0 -109
- package/src/__tests__/runtime/use-session.test.ts +0 -320
- package/src/__tests__/runtime/use-state.test.ts +0 -340
- package/src/__tests__/types/config.test.ts +0 -18
- package/src/cli/adapters/cloudflare.ts +0 -335
- package/src/cli/adapters/netlify.ts +0 -326
- package/src/cli/adapters/vercel.ts +0 -311
- package/src/cli/commands/adapt.ts +0 -84
- package/src/cli/commands/build.ts +0 -165
- package/src/cli/commands/dev.ts +0 -125
- package/src/cli/commands/generate.ts +0 -91
- package/src/cli/commands/preview-isr.ts +0 -172
- package/src/cli/commands/preview.ts +0 -523
- package/src/cli/create/index.ts +0 -275
- package/src/cli/create/templates/shared/.gitignore.tpl +0 -25
- package/src/cli/create/templates/shared/app/layouts/default.ts.tpl +0 -15
- package/src/cli/create/templates/shared/app/pages/index.ts.tpl +0 -8
- package/src/cli/create/templates/shared/index.html.tpl +0 -12
- package/src/cli/create/templates/shared/tsconfig.json.tpl +0 -6
- package/src/cli/create/templates/spa/cer.config.ts.tpl +0 -6
- package/src/cli/create/templates/spa/package.json.tpl +0 -18
- package/src/cli/create/templates/ssg/cer.config.ts.tpl +0 -10
- package/src/cli/create/templates/ssg/package.json.tpl +0 -19
- package/src/cli/create/templates/ssr/cer.config.ts.tpl +0 -6
- package/src/cli/create/templates/ssr/package.json.tpl +0 -18
- package/src/cli/index.ts +0 -22
- package/src/index.ts +0 -20
- package/src/plugin/build-ssg.ts +0 -403
- package/src/plugin/build-ssr.ts +0 -134
- package/src/plugin/content/emitter.ts +0 -50
- package/src/plugin/content/index.ts +0 -233
- package/src/plugin/content/parser.ts +0 -259
- package/src/plugin/content/path-utils.ts +0 -55
- package/src/plugin/content/scanner.ts +0 -26
- package/src/plugin/content/search.ts +0 -28
- package/src/plugin/dev-server.ts +0 -379
- package/src/plugin/dts-generator.ts +0 -273
- package/src/plugin/generated-dir.ts +0 -121
- package/src/plugin/html-post-process.ts +0 -96
- package/src/plugin/index.ts +0 -584
- package/src/plugin/path-utils.ts +0 -186
- package/src/plugin/scanner.ts +0 -65
- package/src/plugin/transforms/auto-import.ts +0 -206
- package/src/plugin/transforms/head-inject.ts +0 -161
- package/src/plugin/virtual/composables.ts +0 -28
- package/src/plugin/virtual/content-components.ts +0 -83
- package/src/plugin/virtual/error.ts +0 -34
- package/src/plugin/virtual/layouts.ts +0 -41
- package/src/plugin/virtual/loading.ts +0 -32
- package/src/plugin/virtual/middleware.ts +0 -45
- package/src/plugin/virtual/plugins.ts +0 -46
- package/src/plugin/virtual/routes.ts +0 -514
- package/src/plugin/virtual/server-api.ts +0 -85
- package/src/plugin/virtual/server-middleware.ts +0 -44
- package/src/runtime/app-template.ts +0 -377
- package/src/runtime/composables/define-middleware.ts +0 -17
- package/src/runtime/composables/define-server-middleware.ts +0 -18
- package/src/runtime/composables/index.ts +0 -27
- package/src/runtime/composables/use-auth.ts +0 -125
- package/src/runtime/composables/use-content-search.ts +0 -205
- package/src/runtime/composables/use-content.ts +0 -146
- package/src/runtime/composables/use-cookie.ts +0 -135
- package/src/runtime/composables/use-fetch.ts +0 -438
- package/src/runtime/composables/use-head.ts +0 -234
- package/src/runtime/composables/use-inject.ts +0 -49
- package/src/runtime/composables/use-locale.ts +0 -109
- package/src/runtime/composables/use-navigate.ts +0 -58
- package/src/runtime/composables/use-page-data.ts +0 -93
- package/src/runtime/composables/use-route.ts +0 -71
- package/src/runtime/composables/use-runtime-config.ts +0 -123
- package/src/runtime/composables/use-seo-meta.ts +0 -80
- package/src/runtime/composables/use-session.ts +0 -186
- package/src/runtime/composables/use-state.ts +0 -92
- package/src/runtime/content/client.ts +0 -168
- package/src/runtime/entry-client-template.ts +0 -39
- package/src/runtime/entry-server-template.ts +0 -493
- package/src/runtime/isr-handler.ts +0 -184
- package/src/runtime/oauth/handler.ts +0 -407
- package/src/runtime/oauth/index.ts +0 -49
- package/src/runtime/oauth/providers.ts +0 -38
- package/src/types/api.ts +0 -40
- package/src/types/config.ts +0 -379
- package/src/types/content.ts +0 -66
- package/src/types/index.ts +0 -7
- package/src/types/middleware.ts +0 -63
- package/src/types/page.ts +0 -117
- package/src/types/plugin.ts +0 -34
- package/tsconfig.build.json +0 -10
- package/tsconfig.json +0 -19
- package/vitest.config.ts +0 -33
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tests for the error boundary.
|
|
3
|
-
*
|
|
4
|
-
* SSR: when a page loader throws, the server renders `page-error` (from app/error.ts)
|
|
5
|
-
* instead of crashing, and returns the correct HTTP status code.
|
|
6
|
-
*
|
|
7
|
-
* Client-side: when navigating to a page whose loader throws, currentError is set
|
|
8
|
-
* and the error boundary component is displayed.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
const mode = Cypress.env('mode') as 'spa' | 'ssr' | 'ssg'
|
|
12
|
-
|
|
13
|
-
// Client-side loader error boundary — works in all modes via client-side navigation
|
|
14
|
-
describe('Client-side error boundary — loader throws during navigation', () => {
|
|
15
|
-
it('shows the error boundary after navigating to a page whose loader throws', () => {
|
|
16
|
-
cy.visit('/')
|
|
17
|
-
// Navigate via the router so the client-side loader runs (not a hard page load)
|
|
18
|
-
cy.window().then((win) => {
|
|
19
|
-
// @ts-expect-error cerRouter is a private global
|
|
20
|
-
win.__cerRouter?.push('/loader-error-test')
|
|
21
|
-
})
|
|
22
|
-
cy.get('[data-cy=error-boundary]', { timeout: 5000 }).should('exist')
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
it('error message contains the loader error text after client-side navigation', () => {
|
|
26
|
-
cy.visit('/')
|
|
27
|
-
cy.window().then((win) => {
|
|
28
|
-
// @ts-expect-error cerRouter is a private global
|
|
29
|
-
win.__cerRouter?.push('/loader-error-test')
|
|
30
|
-
})
|
|
31
|
-
cy.get('[data-cy=error-message]', { timeout: 5000 }).should('contain', 'Loader intentionally failed')
|
|
32
|
-
})
|
|
33
|
-
})
|
|
34
|
-
|
|
35
|
-
// SSR loader error boundary — only meaningful when a server render happens
|
|
36
|
-
if (mode === 'ssr') {
|
|
37
|
-
describe('SSR error boundary — loader throws', () => {
|
|
38
|
-
it('returns the status code from the thrown error (503)', () => {
|
|
39
|
-
cy.request({ url: '/loader-error-test', failOnStatusCode: false }).then((response) => {
|
|
40
|
-
expect(response.status).to.eq(503)
|
|
41
|
-
})
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
it('renders page-error element in the server response', () => {
|
|
45
|
-
cy.request({ url: '/loader-error-test', failOnStatusCode: false }).then((response) => {
|
|
46
|
-
expect(response.body).to.include('page-error')
|
|
47
|
-
})
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
it('does not render the normal page heading when loader throws', () => {
|
|
51
|
-
cy.request({ url: '/loader-error-test', failOnStatusCode: false }).then((response) => {
|
|
52
|
-
expect(response.body).not.to.include('loader-error-heading')
|
|
53
|
-
})
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
it('shows the error boundary UI in the browser', () => {
|
|
57
|
-
cy.visit('/loader-error-test', { failOnStatusCode: false })
|
|
58
|
-
cy.get('[data-cy=error-boundary]').should('exist')
|
|
59
|
-
cy.get('[data-cy=error-heading]').should('contain', '503')
|
|
60
|
-
cy.get('[data-cy=error-message]').should('contain', 'Loader intentionally failed')
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
it('exposes a retry button that calls resetError()', () => {
|
|
64
|
-
cy.visit('/loader-error-test', { failOnStatusCode: false })
|
|
65
|
-
cy.get('[data-cy=error-retry]').should('exist')
|
|
66
|
-
})
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
describe('SSR error boundary — loader throws a Response object', () => {
|
|
70
|
-
it('reads the numeric .status from the thrown Response (405)', () => {
|
|
71
|
-
cy.request({ url: '/loader-response-error-test', failOnStatusCode: false }).then((response) => {
|
|
72
|
-
expect(response.status).to.eq(405)
|
|
73
|
-
})
|
|
74
|
-
})
|
|
75
|
-
|
|
76
|
-
it('renders page-error element in the server response for a thrown Response', () => {
|
|
77
|
-
cy.request({ url: '/loader-response-error-test', failOnStatusCode: false }).then((response) => {
|
|
78
|
-
expect(response.body).to.include('page-error')
|
|
79
|
-
})
|
|
80
|
-
})
|
|
81
|
-
|
|
82
|
-
it('does not render the normal page heading when a Response is thrown', () => {
|
|
83
|
-
cy.request({ url: '/loader-response-error-test', failOnStatusCode: false }).then((response) => {
|
|
84
|
-
expect(response.body).not.to.include('loader-response-error-heading')
|
|
85
|
-
})
|
|
86
|
-
})
|
|
87
|
-
})
|
|
88
|
-
}
|
|
@@ -1,254 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Declarative Shadow DOM (DSD) correctness tests.
|
|
3
|
-
*
|
|
4
|
-
* For SSR and SSG modes, validates that the server-rendered HTML:
|
|
5
|
-
* 1. Contains <template shadowrootmode="open"> elements (value must be "open")
|
|
6
|
-
* 2. Each shadow template has its own embedded <style> (JIT CSS not stripped to <head>)
|
|
7
|
-
* 3. Shadow DOM styles are NOT hoisted to <head> (which would break encapsulation)
|
|
8
|
-
* 4. Shadow templates contain the actual rendered component content
|
|
9
|
-
* 5. More complex routes produce more shadow templates than simple routes
|
|
10
|
-
* 6. The loading indicator is NOT present in the initial HTML
|
|
11
|
-
* 7. The DSD polyfill is present and positioned after </cer-layout-view>
|
|
12
|
-
* 8. After JS hydration, custom elements have live, accessible shadow roots
|
|
13
|
-
* 9. Hydration does not duplicate or destroy the pre-rendered shadow content
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
const mode = Cypress.env('mode') as 'spa' | 'ssr' | 'ssg'
|
|
17
|
-
|
|
18
|
-
// All pre-renderable routes
|
|
19
|
-
const ALL_ROUTES = [
|
|
20
|
-
'/',
|
|
21
|
-
'/about',
|
|
22
|
-
'/counter',
|
|
23
|
-
'/head',
|
|
24
|
-
'/blog',
|
|
25
|
-
'/blog/first-post',
|
|
26
|
-
'/blog/second-post',
|
|
27
|
-
'/items/1',
|
|
28
|
-
'/items/2',
|
|
29
|
-
'/login',
|
|
30
|
-
'/plugin-dsd-test',
|
|
31
|
-
]
|
|
32
|
-
|
|
33
|
-
if (mode === 'spa') {
|
|
34
|
-
describe('DSD (skipped in SPA mode)', () => {
|
|
35
|
-
it('SPA mode has no server-side rendering — DSD tests are SSR/SSG only', () => {
|
|
36
|
-
cy.log('DSD tests are skipped in SPA mode')
|
|
37
|
-
})
|
|
38
|
-
})
|
|
39
|
-
} else {
|
|
40
|
-
// ─── Structure: every route has well-formed DSD ───────────────────────────
|
|
41
|
-
|
|
42
|
-
describe('DSD structure — all routes', () => {
|
|
43
|
-
ALL_ROUTES.forEach((path) => {
|
|
44
|
-
it(`${path} has valid DSD structure`, () => {
|
|
45
|
-
cy.assertDSDStructure(path)
|
|
46
|
-
})
|
|
47
|
-
})
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
// ─── Content: shadow templates contain the actual rendered content ─────────
|
|
51
|
-
|
|
52
|
-
describe('DSD content — shadow templates contain rendered output', () => {
|
|
53
|
-
it('home (/): layout nav and page heading are inside shadow templates', () => {
|
|
54
|
-
// layout-default renders site-nav; page-index renders the home heading
|
|
55
|
-
cy.assertDSDContains('/', 'data-cy="site-nav"')
|
|
56
|
-
cy.assertDSDContains('/', 'data-cy="home-heading"')
|
|
57
|
-
cy.assertDSDContains('/', 'Kitchen Sink')
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
it('home (/): ks-badge content is inside a shadow template', () => {
|
|
61
|
-
cy.assertDSDContains('/', 'data-cy="ks-badge"')
|
|
62
|
-
})
|
|
63
|
-
|
|
64
|
-
it('about (/about): page heading is inside a shadow template', () => {
|
|
65
|
-
cy.assertDSDContains('/about', 'data-cy="about-heading"')
|
|
66
|
-
cy.assertDSDContains('/about', 'About')
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
it('counter (/counter): heading and initial count 0 are inside shadow templates', () => {
|
|
70
|
-
cy.assertDSDContains('/counter', 'data-cy="counter-heading"')
|
|
71
|
-
cy.assertDSDContains('/counter', 'Counter')
|
|
72
|
-
cy.assertDSDContains('/counter', 'data-cy="count"')
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
it('blog (/blog): blog heading is inside a shadow template', () => {
|
|
76
|
-
cy.assertDSDContains('/blog', 'data-cy="blog-heading"')
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
it('blog detail (/blog/first-post): post title is inside a shadow template', () => {
|
|
80
|
-
cy.assertDSDContains('/blog/first-post', 'First Post')
|
|
81
|
-
})
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
// ─── Template depth: complex routes have more templates than simple ones ───
|
|
85
|
-
|
|
86
|
-
describe('DSD template count — complexity reflects component tree', () => {
|
|
87
|
-
it('home (/) has more shadow templates than about (/about)', () => {
|
|
88
|
-
cy.request('/').then((homeResp) => {
|
|
89
|
-
cy.request('/about').then((aboutResp) => {
|
|
90
|
-
const homeTemplates = [
|
|
91
|
-
...homeResp.body.matchAll(/<template shadowrootmode="open"/g),
|
|
92
|
-
].length
|
|
93
|
-
const aboutTemplates = [
|
|
94
|
-
...aboutResp.body.matchAll(/<template shadowrootmode="open"/g),
|
|
95
|
-
].length
|
|
96
|
-
|
|
97
|
-
expect(
|
|
98
|
-
homeTemplates,
|
|
99
|
-
'home page (default layout + page-index + ks-badge) should have more templates than about',
|
|
100
|
-
).to.be.greaterThan(aboutTemplates)
|
|
101
|
-
})
|
|
102
|
-
})
|
|
103
|
-
})
|
|
104
|
-
|
|
105
|
-
it('each route has at least 2 shadow templates (layout + page)', () => {
|
|
106
|
-
ALL_ROUTES.forEach((path) => {
|
|
107
|
-
cy.request(path).then((resp) => {
|
|
108
|
-
const count = [...resp.body.matchAll(/<template shadowrootmode="open"/g)].length
|
|
109
|
-
expect(count, `${path}: should have at least 2 shadow templates`).to.be.at.least(2)
|
|
110
|
-
})
|
|
111
|
-
})
|
|
112
|
-
})
|
|
113
|
-
})
|
|
114
|
-
|
|
115
|
-
// ─── Plugin-registered components get DSD ────────────────────────────────
|
|
116
|
-
//
|
|
117
|
-
// Regression test for the "dual-instance registry" bug:
|
|
118
|
-
// When @jasonshimmy/custom-elements-runtime was in ssr.noExternal, the bundler
|
|
119
|
-
// inlined a separate copy of the runtime's component Map. Plugin files (treated
|
|
120
|
-
// as external) resolved the CER runtime from node_modules at runtime — a
|
|
121
|
-
// different Map instance. Components registered by plugins never appeared in
|
|
122
|
-
// the SSR renderer's registry, so renderToStreamWithJITCSSDSD emitted bare
|
|
123
|
-
// <custom-element> stubs with no DSD → FOUC when the browser upgraded them.
|
|
124
|
-
// The fix: keep @jasonshimmy/custom-elements-runtime external so all code
|
|
125
|
-
// (server bundle + plugin packages) shares one node_modules instance.
|
|
126
|
-
|
|
127
|
-
describe('Plugin-registered components — DSD in SSR/SSG', () => {
|
|
128
|
-
it('ks-plugin-card (registered via plugin, not auto-scanned) has a shadow template', () => {
|
|
129
|
-
cy.request('/plugin-dsd-test').then((resp) => {
|
|
130
|
-
const html: string = resp.body
|
|
131
|
-
expect(html, 'ks-plugin-card must appear in rendered HTML').to.include('ks-plugin-card')
|
|
132
|
-
// The component must have a shadow root template — not a bare stub
|
|
133
|
-
const pluginCardIdx = html.indexOf('ks-plugin-card')
|
|
134
|
-
const templateAfterCard = html.indexOf('<template shadowrootmode="open"', pluginCardIdx)
|
|
135
|
-
const nextTagClose = html.indexOf('</ks-plugin-card>', pluginCardIdx)
|
|
136
|
-
expect(templateAfterCard, 'ks-plugin-card must contain a <template shadowrootmode> (DSD)').to.be.greaterThan(-1)
|
|
137
|
-
expect(templateAfterCard, 'shadow template must appear before </ks-plugin-card>').to.be.lessThan(nextTagClose)
|
|
138
|
-
})
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
it('ks-plugin-card DSD contains the card CSS style', () => {
|
|
142
|
-
cy.request('/plugin-dsd-test').then((resp) => {
|
|
143
|
-
cy.assertDSDContains('/plugin-dsd-test', '.card')
|
|
144
|
-
})
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
it('ks-plugin-card has a live shadow root after hydration', () => {
|
|
148
|
-
// ks-plugin-card lives inside page-plugin-dsd-test's shadow root.
|
|
149
|
-
// page-plugin-dsd-test is light DOM of layout-default (slotted), so
|
|
150
|
-
// document.querySelector() can find it directly.
|
|
151
|
-
cy.visit('/plugin-dsd-test')
|
|
152
|
-
cy.get('[data-cy="plugin-dsd-test-page"]').should('exist')
|
|
153
|
-
cy.window().then((win) => {
|
|
154
|
-
const page = win.document.querySelector('page-plugin-dsd-test')
|
|
155
|
-
expect(page, 'page-plugin-dsd-test must exist').to.not.be.null
|
|
156
|
-
const card = page?.shadowRoot?.querySelector('ks-plugin-card')
|
|
157
|
-
expect(card, 'ks-plugin-card must exist inside page-plugin-dsd-test shadow root').to.not.be.null
|
|
158
|
-
expect((card as Element & { shadowRoot: ShadowRoot | null }).shadowRoot,
|
|
159
|
-
'ks-plugin-card must have a live shadow root after hydration').to.not.be.null
|
|
160
|
-
})
|
|
161
|
-
})
|
|
162
|
-
|
|
163
|
-
it('ks-plugin-card slot content is accessible after hydration', () => {
|
|
164
|
-
cy.visit('/plugin-dsd-test')
|
|
165
|
-
cy.get('[data-cy="plugin-card-content"]').should('have.text', 'Card content from plugin component')
|
|
166
|
-
})
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
// ─── DSD polyfill ─────────────────────────────────────────────────────────
|
|
170
|
-
|
|
171
|
-
describe('DSD polyfill', () => {
|
|
172
|
-
it('polyfill script is present in the home page HTML', () => {
|
|
173
|
-
cy.request('/').then((resp) => {
|
|
174
|
-
// The polyfill inlines a function that calls attachShadow on existing templates
|
|
175
|
-
expect(resp.body, 'DSD polyfill should be present in server HTML').to.include(
|
|
176
|
-
'attachShadow',
|
|
177
|
-
)
|
|
178
|
-
})
|
|
179
|
-
})
|
|
180
|
-
|
|
181
|
-
it('polyfill is placed after </cer-layout-view> so it runs outside shadow light DOM', () => {
|
|
182
|
-
cy.request('/').then((resp) => {
|
|
183
|
-
const html: string = resp.body
|
|
184
|
-
const clvEnd = html.lastIndexOf('</cer-layout-view>')
|
|
185
|
-
const polyfillIdx = html.indexOf('attachShadow')
|
|
186
|
-
expect(clvEnd, 'cer-layout-view closing tag must exist').to.be.greaterThan(-1)
|
|
187
|
-
expect(polyfillIdx, 'DSD polyfill must exist').to.be.greaterThan(-1)
|
|
188
|
-
expect(polyfillIdx, 'DSD polyfill must come AFTER </cer-layout-view>').to.be.greaterThan(
|
|
189
|
-
clvEnd,
|
|
190
|
-
)
|
|
191
|
-
})
|
|
192
|
-
})
|
|
193
|
-
})
|
|
194
|
-
|
|
195
|
-
// ─── Loading indicator ────────────────────────────────────────────────────
|
|
196
|
-
|
|
197
|
-
describe('loading indicator absent from initial HTML', () => {
|
|
198
|
-
it('home page: loading indicator is not in the server-rendered HTML', () => {
|
|
199
|
-
cy.request('/').then((resp) => {
|
|
200
|
-
expect(resp.body).not.to.include('page-loading')
|
|
201
|
-
expect(resp.body).not.to.include('data-cy="loading-indicator"')
|
|
202
|
-
})
|
|
203
|
-
})
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
// ─── Hydration: shadow roots are live after JS boots ──────────────────────
|
|
207
|
-
|
|
208
|
-
describe('DSD hydration — shadow roots live after JS', () => {
|
|
209
|
-
it('layout-default has a live shadow root after hydration on home (/)', () => {
|
|
210
|
-
cy.visit('/')
|
|
211
|
-
cy.get('layout-default').should('exist')
|
|
212
|
-
cy.assertShadowRootLive('layout-default')
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
it('page-index has a live shadow root after hydration on home (/)', () => {
|
|
216
|
-
cy.visit('/')
|
|
217
|
-
cy.get('page-index', { includeShadowDom: true }).should('exist')
|
|
218
|
-
cy.assertShadowRootLive('page-index')
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
it('layout-minimal has a live shadow root after hydration on about (/about)', () => {
|
|
222
|
-
cy.visit('/about')
|
|
223
|
-
cy.get('layout-minimal').should('exist')
|
|
224
|
-
cy.assertShadowRootLive('layout-minimal')
|
|
225
|
-
})
|
|
226
|
-
|
|
227
|
-
it('page-about has a live shadow root after hydration on about (/about)', () => {
|
|
228
|
-
cy.visit('/about')
|
|
229
|
-
cy.assertShadowRootLive('page-about')
|
|
230
|
-
})
|
|
231
|
-
|
|
232
|
-
it('page-counter has a live shadow root after hydration on counter (/counter)', () => {
|
|
233
|
-
cy.visit('/counter')
|
|
234
|
-
cy.assertShadowRootLive('page-counter')
|
|
235
|
-
})
|
|
236
|
-
|
|
237
|
-
it('shadow root content survives hydration — home heading still readable', () => {
|
|
238
|
-
cy.visit('/')
|
|
239
|
-
// Content set by DSD pre-render should still be accessible in the live shadow root
|
|
240
|
-
cy.get('[data-cy="home-heading"]').should('have.text', 'Kitchen Sink')
|
|
241
|
-
})
|
|
242
|
-
|
|
243
|
-
it('shadow root content survives hydration — site-nav still rendered', () => {
|
|
244
|
-
cy.visit('/')
|
|
245
|
-
cy.get('[data-cy="site-nav"]').should('exist')
|
|
246
|
-
cy.get('[data-cy="nav-home"]').should('exist')
|
|
247
|
-
})
|
|
248
|
-
|
|
249
|
-
it('shadow root content survives hydration — counter shows initial count 0', () => {
|
|
250
|
-
cy.visit('/counter')
|
|
251
|
-
cy.get('[data-cy="count"]').should('have.text', '0')
|
|
252
|
-
})
|
|
253
|
-
})
|
|
254
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* P2-1: _layout.ts group meta inheritance.
|
|
3
|
-
*
|
|
4
|
-
* Verifies that middleware and layout declared in a directory's _layout.ts
|
|
5
|
-
* are inherited by all pages in that directory, with page-level declarations
|
|
6
|
-
* taking precedence.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
describe('Group meta from _layout.ts (P2-1)', () => {
|
|
10
|
-
context('middleware inheritance', () => {
|
|
11
|
-
it('applies group middleware from _layout.ts to pages in the directory', () => {
|
|
12
|
-
// The group-meta-test/protected.ts page is in a directory with auth middleware
|
|
13
|
-
// declared in _layout.ts — visiting without auth should trigger the middleware
|
|
14
|
-
cy.visit('/group-meta-test/protected', { failOnStatusCode: false })
|
|
15
|
-
// The auth middleware redirects or renders a guard indicator
|
|
16
|
-
cy.get('[data-cy=group-auth-guard]', { timeout: 5000 }).should('exist')
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
it('page-level middleware overrides group middleware', () => {
|
|
20
|
-
// The group-meta-test/custom-mw.ts overrides group middleware with its own
|
|
21
|
-
cy.visit('/group-meta-test/custom-mw', { failOnStatusCode: false })
|
|
22
|
-
cy.get('[data-cy=custom-mw-marker]', { timeout: 5000 }).should('exist')
|
|
23
|
-
})
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
context('layout inheritance', () => {
|
|
27
|
-
it('pages in a group directory use the layout declared in _layout.ts', () => {
|
|
28
|
-
// Use the page that overrides the blocking group middleware so this
|
|
29
|
-
// assertion isolates layout inheritance from the redirect behavior.
|
|
30
|
-
cy.visit('/group-meta-test/custom-mw')
|
|
31
|
-
cy.get('[data-cy=custom-mw-marker]', { timeout: 5000 }).should('exist')
|
|
32
|
-
// The group layout still wraps the page.
|
|
33
|
-
cy.get('[data-cy=group-layout]', { timeout: 5000 }).should('exist')
|
|
34
|
-
})
|
|
35
|
-
})
|
|
36
|
-
})
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useHead() tests — verifies document title and meta tags are set correctly.
|
|
3
|
-
*
|
|
4
|
-
* In SSR/SSG: tags should be in the initial HTML (server-side injection).
|
|
5
|
-
* In all modes: tags should be set after client-side hydration.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const mode = Cypress.env('mode') as 'spa' | 'ssr' | 'ssg'
|
|
9
|
-
|
|
10
|
-
describe('useHead() — document title', () => {
|
|
11
|
-
it('sets title to "Home — Kitchen Sink" on home page', () => {
|
|
12
|
-
cy.visit('/')
|
|
13
|
-
cy.title().should('eq', 'Home — Kitchen Sink')
|
|
14
|
-
})
|
|
15
|
-
|
|
16
|
-
it('sets title to "About — Kitchen Sink" on about page', () => {
|
|
17
|
-
cy.visit('/about')
|
|
18
|
-
cy.title().should('eq', 'About — Kitchen Sink')
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
it('sets title to "Head Test — Kitchen Sink" on head page', () => {
|
|
22
|
-
cy.visit('/head')
|
|
23
|
-
cy.title().should('eq', 'Head Test — Kitchen Sink')
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
it('sets title to "Blog — Kitchen Sink" on blog list page', () => {
|
|
27
|
-
cy.visit('/blog')
|
|
28
|
-
cy.title().should('eq', 'Blog — Kitchen Sink')
|
|
29
|
-
})
|
|
30
|
-
|
|
31
|
-
it('updates title when navigating between pages', () => {
|
|
32
|
-
cy.visit('/')
|
|
33
|
-
cy.title().should('eq', 'Home — Kitchen Sink')
|
|
34
|
-
cy.get('[data-cy=nav-about]').first().click({ force: true })
|
|
35
|
-
cy.title().should('eq', 'About — Kitchen Sink')
|
|
36
|
-
cy.get('[data-cy=about-back]').first().click({ force: true })
|
|
37
|
-
cy.title().should('eq', 'Home — Kitchen Sink')
|
|
38
|
-
})
|
|
39
|
-
})
|
|
40
|
-
|
|
41
|
-
describe('useHead() — meta tags', () => {
|
|
42
|
-
it('sets meta description on home page', () => {
|
|
43
|
-
cy.visit('/')
|
|
44
|
-
cy.get('meta[name="description"]').should('have.attr', 'content', 'Kitchen sink test app.')
|
|
45
|
-
})
|
|
46
|
-
|
|
47
|
-
it('sets meta description on about page', () => {
|
|
48
|
-
cy.visit('/about')
|
|
49
|
-
cy.get('meta[name="description"]').should('have.attr', 'content', 'About the kitchen sink test app.')
|
|
50
|
-
})
|
|
51
|
-
|
|
52
|
-
it('sets meta description on head test page', () => {
|
|
53
|
-
cy.visit('/head')
|
|
54
|
-
cy.get('meta[name="description"]').should('have.attr', 'content', 'A test page for useHead().')
|
|
55
|
-
})
|
|
56
|
-
|
|
57
|
-
it('sets og:title meta on head test page', () => {
|
|
58
|
-
cy.visit('/head')
|
|
59
|
-
cy.get('meta[property="og:title"]').should('have.attr', 'content', 'Head Test')
|
|
60
|
-
})
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
if (mode !== 'spa') {
|
|
64
|
-
describe('useHead() — server-side injection (SSR/SSG)', () => {
|
|
65
|
-
it('home page title is in the initial HTML', () => {
|
|
66
|
-
cy.request('/').then((response) => {
|
|
67
|
-
expect(response.body).to.include('<title>Home — Kitchen Sink</title>')
|
|
68
|
-
})
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
it('about page title is in the initial HTML', () => {
|
|
72
|
-
cy.request('/about').then((response) => {
|
|
73
|
-
expect(response.body).to.include('<title>About — Kitchen Sink</title>')
|
|
74
|
-
})
|
|
75
|
-
})
|
|
76
|
-
|
|
77
|
-
it('head test page title is in the initial HTML', () => {
|
|
78
|
-
cy.request('/head').then((response) => {
|
|
79
|
-
expect(response.body).to.include('<title>Head Test — Kitchen Sink</title>')
|
|
80
|
-
})
|
|
81
|
-
})
|
|
82
|
-
|
|
83
|
-
it('meta description is in the initial HTML for home', () => {
|
|
84
|
-
cy.request('/').then((response) => {
|
|
85
|
-
expect(response.body).to.include('Kitchen sink test app.')
|
|
86
|
-
})
|
|
87
|
-
})
|
|
88
|
-
})
|
|
89
|
-
}
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* E2E tests for i18n routing and useLocale() composable.
|
|
3
|
-
*
|
|
4
|
-
* The kitchen-sink is configured with:
|
|
5
|
-
* locales: ['en', 'fr'], defaultLocale: 'en', strategy: 'prefix_except_default'
|
|
6
|
-
*
|
|
7
|
-
* This means:
|
|
8
|
-
* /i18n-test → renders in default locale (en)
|
|
9
|
-
* /fr/i18n-test → renders in locale (fr)
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
describe('i18n routing — useLocale()', () => {
|
|
13
|
-
context('default locale (unprefixed path)', () => {
|
|
14
|
-
it('renders the i18n-test page at /i18n-test', () => {
|
|
15
|
-
cy.visit('/i18n-test')
|
|
16
|
-
cy.get('[data-cy=i18n-heading]').should('contain', 'i18n Test Page')
|
|
17
|
-
})
|
|
18
|
-
|
|
19
|
-
it('reports "en" as the current locale on /i18n-test', () => {
|
|
20
|
-
cy.visit('/i18n-test')
|
|
21
|
-
cy.get('[data-cy=current-locale]').should('have.text', 'en')
|
|
22
|
-
})
|
|
23
|
-
|
|
24
|
-
it('reports "en" as the defaultLocale', () => {
|
|
25
|
-
cy.visit('/i18n-test')
|
|
26
|
-
cy.get('[data-cy=default-locale]').should('have.text', 'en')
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
it('reports all configured locales', () => {
|
|
30
|
-
cy.visit('/i18n-test')
|
|
31
|
-
cy.get('[data-cy=locales]').should('have.text', 'en,fr')
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
it('switchLocalePath("fr") produces /fr/i18n-test', () => {
|
|
35
|
-
cy.visit('/i18n-test')
|
|
36
|
-
cy.get('[data-cy=switch-to-fr]').should('have.attr', 'href', '/fr/i18n-test')
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
it('switchLocalePath("en") on the default locale keeps the unprefixed path', () => {
|
|
40
|
-
cy.visit('/i18n-test')
|
|
41
|
-
cy.get('[data-cy=switch-to-en]').should('have.attr', 'href', '/i18n-test')
|
|
42
|
-
})
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
context('non-default locale (fr-prefixed path)', () => {
|
|
46
|
-
it('renders the i18n-test page at /fr/i18n-test', () => {
|
|
47
|
-
cy.visit('/fr/i18n-test')
|
|
48
|
-
cy.get('[data-cy=i18n-heading]').should('contain', 'i18n Test Page')
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('reports "fr" as the current locale on /fr/i18n-test', () => {
|
|
52
|
-
cy.visit('/fr/i18n-test')
|
|
53
|
-
cy.get('[data-cy=current-locale]').should('have.text', 'fr')
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
it('switchLocalePath("en") from /fr/i18n-test produces /i18n-test', () => {
|
|
57
|
-
cy.visit('/fr/i18n-test')
|
|
58
|
-
cy.get('[data-cy=switch-to-en]').should('have.attr', 'href', '/i18n-test')
|
|
59
|
-
})
|
|
60
|
-
|
|
61
|
-
it('switchLocalePath("fr") on the fr-locale keeps the fr prefix', () => {
|
|
62
|
-
cy.visit('/fr/i18n-test')
|
|
63
|
-
cy.get('[data-cy=switch-to-fr]').should('have.attr', 'href', '/fr/i18n-test')
|
|
64
|
-
})
|
|
65
|
-
|
|
66
|
-
it('clicking the switch-to-en link navigates to the default-locale path', () => {
|
|
67
|
-
cy.visit('/fr/i18n-test')
|
|
68
|
-
cy.get('[data-cy=switch-to-en]').click({ force: true })
|
|
69
|
-
cy.url().should('include', '/i18n-test')
|
|
70
|
-
cy.url().should('not.include', '/fr/')
|
|
71
|
-
})
|
|
72
|
-
|
|
73
|
-
it('clicking the switch-to-fr link from /i18n-test navigates to /fr/i18n-test', () => {
|
|
74
|
-
cy.visit('/i18n-test')
|
|
75
|
-
cy.get('[data-cy=switch-to-fr]').click({ force: true })
|
|
76
|
-
cy.url().should('include', '/fr/i18n-test')
|
|
77
|
-
})
|
|
78
|
-
})
|
|
79
|
-
})
|