devskill 2.0.2
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/README.md +123 -0
- package/README.vn.md +104 -0
- package/SKILL_GUIDE.vn.md +252 -0
- package/bin/devskill.js +11 -0
- package/meta.ts +123 -0
- package/package.json +21 -0
- package/publish.sh +50 -0
- package/scripts/cli.ts +556 -0
- package/skills/builderx_api-contexts/SKILL.md +63 -0
- package/skills/builderx_api-contexts/references/core-multi-outbox.md +57 -0
- package/skills/builderx_api-controllers/SKILL.md +49 -0
- package/skills/builderx_api-controllers/references/core-fallback.md +62 -0
- package/skills/builderx_api-schemas/SKILL.md +76 -0
- package/skills/builderx_api-schemas/references/core-schema.md +78 -0
- package/skills/builderx_spa-api/SKILL.md +67 -0
- package/skills/builderx_spa-api/references/base-api.md +97 -0
- package/skills/builderx_spa-api/references/fetch.md +70 -0
- package/skills/builderx_spa-design/SKILL.md +82 -0
- package/skills/builderx_spa-design/references/core-text-design.md +64 -0
- package/skills/builderx_spa-design/references/features-feedback-actions.md +76 -0
- package/skills/builderx_spa-design/references/features-forms.md +91 -0
- package/skills/builderx_spa-design/references/features-layout-navigation.md +121 -0
- package/skills/builderx_spa-permission/SKILL.md +38 -0
- package/skills/builderx_spa-permission/references/has-permission.md +34 -0
- package/skills/composition-patterns/AGENTS.md +946 -0
- package/skills/composition-patterns/README.md +60 -0
- package/skills/composition-patterns/SKILL.md +89 -0
- package/skills/composition-patterns/SYNC.md +5 -0
- package/skills/composition-patterns/metadata.json +11 -0
- package/skills/composition-patterns/rules/_sections.md +29 -0
- package/skills/composition-patterns/rules/_template.md +24 -0
- package/skills/composition-patterns/rules/architecture-avoid-boolean-props.md +100 -0
- package/skills/composition-patterns/rules/architecture-compound-components.md +112 -0
- package/skills/composition-patterns/rules/patterns-children-over-render-props.md +87 -0
- package/skills/composition-patterns/rules/patterns-explicit-variants.md +100 -0
- package/skills/composition-patterns/rules/react19-no-forwardref.md +42 -0
- package/skills/composition-patterns/rules/state-context-interface.md +191 -0
- package/skills/composition-patterns/rules/state-decouple-implementation.md +113 -0
- package/skills/composition-patterns/rules/state-lift-state.md +125 -0
- package/skills/deploy-to-vercel/Archive.zip +0 -0
- package/skills/deploy-to-vercel/SKILL.md +296 -0
- package/skills/deploy-to-vercel/SYNC.md +5 -0
- package/skills/deploy-to-vercel/resources/deploy-codex.sh +301 -0
- package/skills/deploy-to-vercel/resources/deploy.sh +301 -0
- package/skills/pinia/SKILL.md +105 -0
- package/skills/pinia/references/api-in-composables.md +139 -0
- package/skills/pinia/references/setup-stores.md +105 -0
- package/skills/pinia/references/using-in-components.md +91 -0
- package/skills/pinia-options/SKILL.md +72 -0
- package/skills/pinia-options/references/core-option-stores.md +149 -0
- package/skills/pinia-options/references/using-in-options-api.md +105 -0
- package/skills/react-best-practices/AGENTS.md +3373 -0
- package/skills/react-best-practices/README.md +123 -0
- package/skills/react-best-practices/SKILL.md +143 -0
- package/skills/react-best-practices/SYNC.md +5 -0
- package/skills/react-best-practices/metadata.json +15 -0
- package/skills/react-best-practices/rules/_sections.md +46 -0
- package/skills/react-best-practices/rules/_template.md +28 -0
- package/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/skills/react-best-practices/rules/advanced-init-once.md +42 -0
- package/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
- package/skills/react-best-practices/rules/async-api-routes.md +38 -0
- package/skills/react-best-practices/rules/async-defer-await.md +80 -0
- package/skills/react-best-practices/rules/async-dependencies.md +51 -0
- package/skills/react-best-practices/rules/async-parallel.md +28 -0
- package/skills/react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/skills/react-best-practices/rules/bundle-barrel-imports.md +59 -0
- package/skills/react-best-practices/rules/bundle-conditional.md +31 -0
- package/skills/react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/skills/react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/skills/react-best-practices/rules/bundle-preload.md +50 -0
- package/skills/react-best-practices/rules/client-event-listeners.md +74 -0
- package/skills/react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/skills/react-best-practices/rules/client-swr-dedup.md +56 -0
- package/skills/react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/skills/react-best-practices/rules/js-cache-function-results.md +80 -0
- package/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
- package/skills/react-best-practices/rules/js-cache-storage.md +70 -0
- package/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
- package/skills/react-best-practices/rules/js-early-exit.md +50 -0
- package/skills/react-best-practices/rules/js-flatmap-filter.md +60 -0
- package/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/skills/react-best-practices/rules/js-index-maps.md +37 -0
- package/skills/react-best-practices/rules/js-length-check-first.md +49 -0
- package/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
- package/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/skills/react-best-practices/rules/rendering-activity.md +26 -0
- package/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/skills/react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/skills/react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/skills/react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/skills/react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/skills/react-best-practices/rules/rendering-resource-hints.md +85 -0
- package/skills/react-best-practices/rules/rendering-script-defer-async.md +68 -0
- package/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/skills/react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
- package/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
- package/skills/react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/skills/react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/skills/react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/skills/react-best-practices/rules/rerender-memo.md +44 -0
- package/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/skills/react-best-practices/rules/rerender-no-inline-components.md +82 -0
- package/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/skills/react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
- package/skills/react-best-practices/rules/rerender-transitions.md +40 -0
- package/skills/react-best-practices/rules/rerender-use-deferred-value.md +59 -0
- package/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/skills/react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/skills/react-best-practices/rules/server-auth-actions.md +96 -0
- package/skills/react-best-practices/rules/server-cache-lru.md +41 -0
- package/skills/react-best-practices/rules/server-cache-react.md +76 -0
- package/skills/react-best-practices/rules/server-dedup-props.md +65 -0
- package/skills/react-best-practices/rules/server-hoist-static-io.md +142 -0
- package/skills/react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/skills/react-best-practices/rules/server-serialization.md +38 -0
- package/skills/react-native-skills/AGENTS.md +2897 -0
- package/skills/react-native-skills/README.md +165 -0
- package/skills/react-native-skills/SKILL.md +121 -0
- package/skills/react-native-skills/SYNC.md +5 -0
- package/skills/react-native-skills/metadata.json +16 -0
- package/skills/react-native-skills/rules/_sections.md +86 -0
- package/skills/react-native-skills/rules/_template.md +28 -0
- package/skills/react-native-skills/rules/animation-derived-value.md +53 -0
- package/skills/react-native-skills/rules/animation-gesture-detector-press.md +95 -0
- package/skills/react-native-skills/rules/animation-gpu-properties.md +65 -0
- package/skills/react-native-skills/rules/design-system-compound-components.md +66 -0
- package/skills/react-native-skills/rules/fonts-config-plugin.md +71 -0
- package/skills/react-native-skills/rules/imports-design-system-folder.md +68 -0
- package/skills/react-native-skills/rules/js-hoist-intl.md +61 -0
- package/skills/react-native-skills/rules/list-performance-callbacks.md +44 -0
- package/skills/react-native-skills/rules/list-performance-function-references.md +132 -0
- package/skills/react-native-skills/rules/list-performance-images.md +53 -0
- package/skills/react-native-skills/rules/list-performance-inline-objects.md +97 -0
- package/skills/react-native-skills/rules/list-performance-item-expensive.md +94 -0
- package/skills/react-native-skills/rules/list-performance-item-memo.md +82 -0
- package/skills/react-native-skills/rules/list-performance-item-types.md +104 -0
- package/skills/react-native-skills/rules/list-performance-virtualize.md +67 -0
- package/skills/react-native-skills/rules/monorepo-native-deps-in-app.md +46 -0
- package/skills/react-native-skills/rules/monorepo-single-dependency-versions.md +63 -0
- package/skills/react-native-skills/rules/navigation-native-navigators.md +188 -0
- package/skills/react-native-skills/rules/react-compiler-destructure-functions.md +50 -0
- package/skills/react-native-skills/rules/react-compiler-reanimated-shared-values.md +48 -0
- package/skills/react-native-skills/rules/react-state-dispatcher.md +91 -0
- package/skills/react-native-skills/rules/react-state-fallback.md +56 -0
- package/skills/react-native-skills/rules/react-state-minimize.md +65 -0
- package/skills/react-native-skills/rules/rendering-no-falsy-and.md +74 -0
- package/skills/react-native-skills/rules/rendering-text-in-text-component.md +36 -0
- package/skills/react-native-skills/rules/scroll-position-no-state.md +82 -0
- package/skills/react-native-skills/rules/state-ground-truth.md +80 -0
- package/skills/react-native-skills/rules/ui-expo-image.md +66 -0
- package/skills/react-native-skills/rules/ui-image-gallery.md +104 -0
- package/skills/react-native-skills/rules/ui-measure-views.md +78 -0
- package/skills/react-native-skills/rules/ui-menus.md +174 -0
- package/skills/react-native-skills/rules/ui-native-modals.md +77 -0
- package/skills/react-native-skills/rules/ui-pressable.md +61 -0
- package/skills/react-native-skills/rules/ui-safe-area-scroll.md +65 -0
- package/skills/react-native-skills/rules/ui-scrollview-content-inset.md +45 -0
- package/skills/react-native-skills/rules/ui-styling.md +87 -0
- package/skills/slidev/LICENSE.md +21 -0
- package/skills/slidev/README.md +61 -0
- package/skills/slidev/SKILL.md +189 -0
- package/skills/slidev/SYNC.md +5 -0
- package/skills/slidev/references/animation-click-marker.md +37 -0
- package/skills/slidev/references/animation-drawing.md +68 -0
- package/skills/slidev/references/animation-rough-marker.md +53 -0
- package/skills/slidev/references/api-slide-hooks.md +37 -0
- package/skills/slidev/references/build-og-image.md +36 -0
- package/skills/slidev/references/build-pdf.md +40 -0
- package/skills/slidev/references/build-remote-assets.md +34 -0
- package/skills/slidev/references/build-seo-meta.md +43 -0
- package/skills/slidev/references/code-groups.md +64 -0
- package/skills/slidev/references/code-import-snippet.md +55 -0
- package/skills/slidev/references/code-line-highlighting.md +50 -0
- package/skills/slidev/references/code-line-numbers.md +46 -0
- package/skills/slidev/references/code-magic-move.md +57 -0
- package/skills/slidev/references/code-max-height.md +37 -0
- package/skills/slidev/references/code-twoslash.md +42 -0
- package/skills/slidev/references/core-animations.md +196 -0
- package/skills/slidev/references/core-cli.md +140 -0
- package/skills/slidev/references/core-components.md +197 -0
- package/skills/slidev/references/core-exporting.md +148 -0
- package/skills/slidev/references/core-frontmatter.md +195 -0
- package/skills/slidev/references/core-global-context.md +155 -0
- package/skills/slidev/references/core-headmatter.md +188 -0
- package/skills/slidev/references/core-hosting.md +152 -0
- package/skills/slidev/references/core-layouts.md +286 -0
- package/skills/slidev/references/core-syntax.md +155 -0
- package/skills/slidev/references/diagram-latex.md +55 -0
- package/skills/slidev/references/diagram-mermaid.md +44 -0
- package/skills/slidev/references/diagram-plantuml.md +45 -0
- package/skills/slidev/references/editor-monaco-run.md +44 -0
- package/skills/slidev/references/editor-monaco-write.md +24 -0
- package/skills/slidev/references/editor-monaco.md +50 -0
- package/skills/slidev/references/editor-prettier.md +40 -0
- package/skills/slidev/references/editor-side.md +23 -0
- package/skills/slidev/references/editor-vscode.md +55 -0
- package/skills/slidev/references/layout-canvas-size.md +25 -0
- package/skills/slidev/references/layout-draggable.md +57 -0
- package/skills/slidev/references/layout-global-layers.md +50 -0
- package/skills/slidev/references/layout-slots.md +75 -0
- package/skills/slidev/references/layout-transform.md +33 -0
- package/skills/slidev/references/layout-zoom.md +39 -0
- package/skills/slidev/references/presenter-notes-ruby.md +35 -0
- package/skills/slidev/references/presenter-recording.md +30 -0
- package/skills/slidev/references/presenter-remote.md +40 -0
- package/skills/slidev/references/presenter-timer.md +34 -0
- package/skills/slidev/references/style-direction.md +34 -0
- package/skills/slidev/references/style-icons.md +46 -0
- package/skills/slidev/references/style-scoped.md +50 -0
- package/skills/slidev/references/syntax-block-frontmatter.md +39 -0
- package/skills/slidev/references/syntax-frontmatter-merging.md +49 -0
- package/skills/slidev/references/syntax-importing-slides.md +60 -0
- package/skills/slidev/references/syntax-mdc.md +51 -0
- package/skills/slidev/references/tool-eject-theme.md +27 -0
- package/skills/tsdown/LICENSE.md +22 -0
- package/skills/tsdown/README.md +77 -0
- package/skills/tsdown/SKILL.md +407 -0
- package/skills/tsdown/SYNC.md +5 -0
- package/skills/tsdown/references/README.md +139 -0
- package/skills/tsdown/references/advanced-benchmark.md +8 -0
- package/skills/tsdown/references/advanced-ci.md +89 -0
- package/skills/tsdown/references/advanced-hooks.md +363 -0
- package/skills/tsdown/references/advanced-plugins.md +381 -0
- package/skills/tsdown/references/advanced-programmatic.md +378 -0
- package/skills/tsdown/references/advanced-rolldown-options.md +117 -0
- package/skills/tsdown/references/guide-getting-started.md +178 -0
- package/skills/tsdown/references/guide-introduction.md +42 -0
- package/skills/tsdown/references/guide-migrate-from-tsup.md +189 -0
- package/skills/tsdown/references/option-cjs-default.md +98 -0
- package/skills/tsdown/references/option-cleaning.md +275 -0
- package/skills/tsdown/references/option-config-file.md +281 -0
- package/skills/tsdown/references/option-css.md +301 -0
- package/skills/tsdown/references/option-dependencies.md +385 -0
- package/skills/tsdown/references/option-dts.md +251 -0
- package/skills/tsdown/references/option-entry.md +211 -0
- package/skills/tsdown/references/option-exe.md +120 -0
- package/skills/tsdown/references/option-lint.md +127 -0
- package/skills/tsdown/references/option-log-level.md +91 -0
- package/skills/tsdown/references/option-minification.md +177 -0
- package/skills/tsdown/references/option-output-directory.md +270 -0
- package/skills/tsdown/references/option-output-format.md +181 -0
- package/skills/tsdown/references/option-package-exports.md +320 -0
- package/skills/tsdown/references/option-platform.md +256 -0
- package/skills/tsdown/references/option-root.md +88 -0
- package/skills/tsdown/references/option-shims.md +299 -0
- package/skills/tsdown/references/option-sourcemap.md +301 -0
- package/skills/tsdown/references/option-target.md +222 -0
- package/skills/tsdown/references/option-tree-shaking.md +335 -0
- package/skills/tsdown/references/option-unbundle.md +310 -0
- package/skills/tsdown/references/option-watch-mode.md +261 -0
- package/skills/tsdown/references/recipe-react.md +338 -0
- package/skills/tsdown/references/recipe-solid.md +46 -0
- package/skills/tsdown/references/recipe-svelte.md +54 -0
- package/skills/tsdown/references/recipe-vue.md +387 -0
- package/skills/tsdown/references/recipe-wasm.md +125 -0
- package/skills/tsdown/references/reference-cli.md +472 -0
- package/skills/turborepo/LICENSE.md +7 -0
- package/skills/turborepo/SKILL.md +951 -0
- package/skills/turborepo/SYNC.md +5 -0
- package/skills/turborepo/command/turborepo.md +70 -0
- package/skills/turborepo/references/best-practices/RULE.md +241 -0
- package/skills/turborepo/references/best-practices/dependencies.md +246 -0
- package/skills/turborepo/references/best-practices/packages.md +335 -0
- package/skills/turborepo/references/best-practices/structure.md +297 -0
- package/skills/turborepo/references/boundaries/RULE.md +126 -0
- package/skills/turborepo/references/caching/RULE.md +153 -0
- package/skills/turborepo/references/caching/gotchas.md +190 -0
- package/skills/turborepo/references/caching/remote-cache.md +127 -0
- package/skills/turborepo/references/ci/RULE.md +79 -0
- package/skills/turborepo/references/ci/github-actions.md +162 -0
- package/skills/turborepo/references/ci/patterns.md +145 -0
- package/skills/turborepo/references/ci/vercel.md +103 -0
- package/skills/turborepo/references/cli/RULE.md +100 -0
- package/skills/turborepo/references/cli/commands.md +297 -0
- package/skills/turborepo/references/configuration/RULE.md +235 -0
- package/skills/turborepo/references/configuration/global-options.md +239 -0
- package/skills/turborepo/references/configuration/gotchas.md +368 -0
- package/skills/turborepo/references/configuration/tasks.md +325 -0
- package/skills/turborepo/references/environment/RULE.md +123 -0
- package/skills/turborepo/references/environment/gotchas.md +175 -0
- package/skills/turborepo/references/environment/modes.md +101 -0
- package/skills/turborepo/references/filtering/RULE.md +148 -0
- package/skills/turborepo/references/filtering/patterns.md +152 -0
- package/skills/turborepo/references/watch/RULE.md +99 -0
- package/skills/vercel-cli-with-tokens/SKILL.md +328 -0
- package/skills/vercel-cli-with-tokens/SYNC.md +5 -0
- package/skills/vue/SKILL.md +90 -0
- package/skills/vue/references/composables.md +54 -0
- package/skills/vue/references/lifecycle.md +31 -0
- package/skills/vue/references/props-emits.md +62 -0
- package/skills/vue/references/provide-inject.md +47 -0
- package/skills/vue/references/state.md +65 -0
- package/skills/vue-antdv-tailwind/SKILL.md +33 -0
- package/skills/vue-antdv-tailwind/references/styling-rules.md +61 -0
- package/skills/vue-best-practices/LICENSE.md +21 -0
- package/skills/vue-best-practices/SKILL.md +154 -0
- package/skills/vue-best-practices/SYNC.md +5 -0
- package/skills/vue-best-practices/references/animation-class-based-technique.md +254 -0
- package/skills/vue-best-practices/references/animation-state-driven-technique.md +291 -0
- package/skills/vue-best-practices/references/component-async.md +97 -0
- package/skills/vue-best-practices/references/component-data-flow.md +307 -0
- package/skills/vue-best-practices/references/component-fallthrough-attrs.md +174 -0
- package/skills/vue-best-practices/references/component-keep-alive.md +137 -0
- package/skills/vue-best-practices/references/component-slots.md +216 -0
- package/skills/vue-best-practices/references/component-suspense.md +228 -0
- package/skills/vue-best-practices/references/component-teleport.md +108 -0
- package/skills/vue-best-practices/references/component-transition-group.md +128 -0
- package/skills/vue-best-practices/references/component-transition.md +125 -0
- package/skills/vue-best-practices/references/composables.md +290 -0
- package/skills/vue-best-practices/references/directives.md +162 -0
- package/skills/vue-best-practices/references/perf-avoid-component-abstraction-in-lists.md +159 -0
- package/skills/vue-best-practices/references/perf-v-once-v-memo-directives.md +182 -0
- package/skills/vue-best-practices/references/perf-virtualize-large-lists.md +187 -0
- package/skills/vue-best-practices/references/plugins.md +166 -0
- package/skills/vue-best-practices/references/reactivity.md +344 -0
- package/skills/vue-best-practices/references/render-functions.md +201 -0
- package/skills/vue-best-practices/references/sfc.md +310 -0
- package/skills/vue-best-practices/references/state-management.md +135 -0
- package/skills/vue-best-practices/references/updated-hook-performance.md +187 -0
- package/skills/vue-jsx-best-practices/LICENSE.md +21 -0
- package/skills/vue-jsx-best-practices/SKILL.md +12 -0
- package/skills/vue-jsx-best-practices/SYNC.md +5 -0
- package/skills/vue-jsx-best-practices/reference/render-function-jsx-vue-vs-react.md +141 -0
- package/skills/vue-options/SKILL.md +98 -0
- package/skills/vue-options/references/lifecycle.md +107 -0
- package/skills/vue-options/references/mixins.md +96 -0
- package/skills/vue-options/references/props-emits.md +106 -0
- package/skills/vue-options/references/provide-inject.md +92 -0
- package/skills/vue-options/references/state.md +115 -0
- package/skills/vue-options-api-best-practices/LICENSE.md +21 -0
- package/skills/vue-options-api-best-practices/SKILL.md +23 -0
- package/skills/vue-options-api-best-practices/SYNC.md +5 -0
- package/skills/vue-options-api-best-practices/reference/no-arrow-functions-in-lifecycle-hooks.md +95 -0
- package/skills/vue-options-api-best-practices/reference/no-arrow-functions-in-methods.md +68 -0
- package/skills/vue-options-api-best-practices/reference/stateful-methods-lifecycle.md +61 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-arrow-functions-validators.md +141 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-computed-return-types.md +192 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-proptype-complex-types.md +212 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-provide-inject-limitations.md +135 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-type-event-handlers.md +202 -0
- package/skills/vue-options-api-best-practices/reference/ts-options-api-use-definecomponent.md +172 -0
- package/skills/vue-options-api-best-practices/reference/ts-strict-mode-options-api.md +197 -0
- package/skills/vue-pinia-best-practices/LICENSE.md +21 -0
- package/skills/vue-pinia-best-practices/SKILL.md +21 -0
- package/skills/vue-pinia-best-practices/SYNC.md +5 -0
- package/skills/vue-pinia-best-practices/reference/pinia-no-active-pinia-error.md +248 -0
- package/skills/vue-pinia-best-practices/reference/pinia-setup-store-return-all-state.md +227 -0
- package/skills/vue-pinia-best-practices/reference/pinia-store-destructuring-breaks-reactivity.md +193 -0
- package/skills/vue-pinia-best-practices/reference/state-url-for-ephemeral-filters.md +238 -0
- package/skills/vue-pinia-best-practices/reference/state-use-pinia-for-large-apps.md +262 -0
- package/skills/vue-pinia-best-practices/reference/store-method-binding-parentheses.md +191 -0
- package/skills/vue-router-best-practices/LICENSE.md +21 -0
- package/skills/vue-router-best-practices/SKILL.md +23 -0
- package/skills/vue-router-best-practices/SYNC.md +5 -0
- package/skills/vue-router-best-practices/reference/router-beforeenter-no-param-trigger.md +167 -0
- package/skills/vue-router-best-practices/reference/router-beforerouteenter-no-this.md +176 -0
- package/skills/vue-router-best-practices/reference/router-guard-async-await-pattern.md +227 -0
- package/skills/vue-router-best-practices/reference/router-navigation-guard-infinite-loop.md +187 -0
- package/skills/vue-router-best-practices/reference/router-navigation-guard-next-deprecated.md +150 -0
- package/skills/vue-router-best-practices/reference/router-param-change-no-lifecycle.md +181 -0
- package/skills/vue-router-best-practices/reference/router-simple-routing-cleanup.md +209 -0
- package/skills/vue-router-best-practices/reference/router-use-vue-router-for-production.md +183 -0
- package/skills/vue-testing-best-practices/LICENSE.md +21 -0
- package/skills/vue-testing-best-practices/SKILL.md +29 -0
- package/skills/vue-testing-best-practices/SYNC.md +5 -0
- package/skills/vue-testing-best-practices/reference/async-component-testing.md +163 -0
- package/skills/vue-testing-best-practices/reference/teleport-testing-complexity.md +158 -0
- package/skills/vue-testing-best-practices/reference/testing-async-await-flushpromises.md +175 -0
- package/skills/vue-testing-best-practices/reference/testing-browser-vs-node-runners.md +208 -0
- package/skills/vue-testing-best-practices/reference/testing-component-blackbox-approach.md +144 -0
- package/skills/vue-testing-best-practices/reference/testing-composables-helper-wrapper.md +238 -0
- package/skills/vue-testing-best-practices/reference/testing-e2e-playwright-recommended.md +242 -0
- package/skills/vue-testing-best-practices/reference/testing-no-snapshot-only.md +197 -0
- package/skills/vue-testing-best-practices/reference/testing-pinia-store-setup.md +228 -0
- package/skills/vue-testing-best-practices/reference/testing-suspense-async-components.md +229 -0
- package/skills/vue-testing-best-practices/reference/testing-vitest-recommended-for-vue.md +204 -0
- package/skills/vueuse-functions/LICENSE.md +21 -0
- package/skills/vueuse-functions/SKILL.md +419 -0
- package/skills/vueuse-functions/SYNC.md +5 -0
- package/skills/vueuse-functions/references/computedAsync.md +195 -0
- package/skills/vueuse-functions/references/computedEager.md +62 -0
- package/skills/vueuse-functions/references/computedInject.md +137 -0
- package/skills/vueuse-functions/references/computedWithControl.md +98 -0
- package/skills/vueuse-functions/references/createEventHook.md +86 -0
- package/skills/vueuse-functions/references/createGenericProjection.md +25 -0
- package/skills/vueuse-functions/references/createGlobalState.md +95 -0
- package/skills/vueuse-functions/references/createInjectionState.md +215 -0
- package/skills/vueuse-functions/references/createProjection.md +31 -0
- package/skills/vueuse-functions/references/createRef.md +54 -0
- package/skills/vueuse-functions/references/createReusableTemplate.md +357 -0
- package/skills/vueuse-functions/references/createSharedComposable.md +42 -0
- package/skills/vueuse-functions/references/createTemplatePromise.md +306 -0
- package/skills/vueuse-functions/references/createUnrefFn.md +51 -0
- package/skills/vueuse-functions/references/extendRef.md +76 -0
- package/skills/vueuse-functions/references/from.md +80 -0
- package/skills/vueuse-functions/references/get.md +30 -0
- package/skills/vueuse-functions/references/injectLocal.md +35 -0
- package/skills/vueuse-functions/references/isDefined.md +31 -0
- package/skills/vueuse-functions/references/logicAnd.md +40 -0
- package/skills/vueuse-functions/references/logicNot.md +36 -0
- package/skills/vueuse-functions/references/logicOr.md +40 -0
- package/skills/vueuse-functions/references/makeDestructurable.md +41 -0
- package/skills/vueuse-functions/references/onClickOutside.md +221 -0
- package/skills/vueuse-functions/references/onElementRemoval.md +88 -0
- package/skills/vueuse-functions/references/onKeyStroke.md +211 -0
- package/skills/vueuse-functions/references/onLongPress.md +227 -0
- package/skills/vueuse-functions/references/onStartTyping.md +53 -0
- package/skills/vueuse-functions/references/provideLocal.md +37 -0
- package/skills/vueuse-functions/references/reactify.md +144 -0
- package/skills/vueuse-functions/references/reactifyObject.md +62 -0
- package/skills/vueuse-functions/references/reactiveComputed.md +34 -0
- package/skills/vueuse-functions/references/reactiveOmit.md +86 -0
- package/skills/vueuse-functions/references/reactivePick.md +106 -0
- package/skills/vueuse-functions/references/refAutoReset.md +46 -0
- package/skills/vueuse-functions/references/refDebounced.md +81 -0
- package/skills/vueuse-functions/references/refDefault.md +36 -0
- package/skills/vueuse-functions/references/refManualReset.md +44 -0
- package/skills/vueuse-functions/references/refThrottled.md +99 -0
- package/skills/vueuse-functions/references/refWithControl.md +146 -0
- package/skills/vueuse-functions/references/set.md +30 -0
- package/skills/vueuse-functions/references/syncRef.md +195 -0
- package/skills/vueuse-functions/references/syncRefs.md +128 -0
- package/skills/vueuse-functions/references/templateRef.md +86 -0
- package/skills/vueuse-functions/references/toObserver.md +38 -0
- package/skills/vueuse-functions/references/toReactive.md +41 -0
- package/skills/vueuse-functions/references/toRef.md +75 -0
- package/skills/vueuse-functions/references/toRefs.md +81 -0
- package/skills/vueuse-functions/references/tryOnBeforeMount.md +34 -0
- package/skills/vueuse-functions/references/tryOnBeforeUnmount.md +32 -0
- package/skills/vueuse-functions/references/tryOnMounted.md +34 -0
- package/skills/vueuse-functions/references/tryOnScopeDispose.md +31 -0
- package/skills/vueuse-functions/references/tryOnUnmounted.md +32 -0
- package/skills/vueuse-functions/references/unrefElement.md +54 -0
- package/skills/vueuse-functions/references/until.md +161 -0
- package/skills/vueuse-functions/references/useAbs.md +31 -0
- package/skills/vueuse-functions/references/useActiveElement.md +85 -0
- package/skills/vueuse-functions/references/useAnimate.md +181 -0
- package/skills/vueuse-functions/references/useArrayDifference.md +84 -0
- package/skills/vueuse-functions/references/useArrayEvery.md +59 -0
- package/skills/vueuse-functions/references/useArrayFilter.md +63 -0
- package/skills/vueuse-functions/references/useArrayFind.md +50 -0
- package/skills/vueuse-functions/references/useArrayFindIndex.md +59 -0
- package/skills/vueuse-functions/references/useArrayFindLast.md +52 -0
- package/skills/vueuse-functions/references/useArrayIncludes.md +63 -0
- package/skills/vueuse-functions/references/useArrayJoin.md +74 -0
- package/skills/vueuse-functions/references/useArrayMap.md +59 -0
- package/skills/vueuse-functions/references/useArrayReduce.md +81 -0
- package/skills/vueuse-functions/references/useArraySome.md +59 -0
- package/skills/vueuse-functions/references/useArrayUnique.md +76 -0
- package/skills/vueuse-functions/references/useAsyncQueue.md +136 -0
- package/skills/vueuse-functions/references/useAsyncState.md +185 -0
- package/skills/vueuse-functions/references/useAsyncValidator.md +70 -0
- package/skills/vueuse-functions/references/useAuth.md +123 -0
- package/skills/vueuse-functions/references/useAverage.md +36 -0
- package/skills/vueuse-functions/references/useAxios.md +325 -0
- package/skills/vueuse-functions/references/useBase64.md +136 -0
- package/skills/vueuse-functions/references/useBattery.md +78 -0
- package/skills/vueuse-functions/references/useBluetooth.md +175 -0
- package/skills/vueuse-functions/references/useBreakpoints.md +172 -0
- package/skills/vueuse-functions/references/useBroadcastChannel.md +74 -0
- package/skills/vueuse-functions/references/useBrowserLocation.md +83 -0
- package/skills/vueuse-functions/references/useCached.md +52 -0
- package/skills/vueuse-functions/references/useCeil.md +31 -0
- package/skills/vueuse-functions/references/useChangeCase.md +79 -0
- package/skills/vueuse-functions/references/useClamp.md +85 -0
- package/skills/vueuse-functions/references/useClipboard.md +123 -0
- package/skills/vueuse-functions/references/useClipboardItems.md +94 -0
- package/skills/vueuse-functions/references/useCloned.md +91 -0
- package/skills/vueuse-functions/references/useColorMode.md +172 -0
- package/skills/vueuse-functions/references/useConfirmDialog.md +159 -0
- package/skills/vueuse-functions/references/useCookies.md +162 -0
- package/skills/vueuse-functions/references/useCountdown.md +105 -0
- package/skills/vueuse-functions/references/useCounter.md +86 -0
- package/skills/vueuse-functions/references/useCssSupports.md +35 -0
- package/skills/vueuse-functions/references/useCssVar.md +50 -0
- package/skills/vueuse-functions/references/useCurrentElement.md +61 -0
- package/skills/vueuse-functions/references/useCycleList.md +75 -0
- package/skills/vueuse-functions/references/useDark.md +144 -0
- package/skills/vueuse-functions/references/useDateFormat.md +145 -0
- package/skills/vueuse-functions/references/useDebounceFn.md +100 -0
- package/skills/vueuse-functions/references/useDebouncedRefHistory.md +40 -0
- package/skills/vueuse-functions/references/useDeviceMotion.md +86 -0
- package/skills/vueuse-functions/references/useDeviceOrientation.md +62 -0
- package/skills/vueuse-functions/references/useDevicePixelRatio.md +44 -0
- package/skills/vueuse-functions/references/useDevicesList.md +90 -0
- package/skills/vueuse-functions/references/useDisplayMedia.md +71 -0
- package/skills/vueuse-functions/references/useDocumentVisibility.md +45 -0
- package/skills/vueuse-functions/references/useDraggable.md +317 -0
- package/skills/vueuse-functions/references/useDrauu.md +65 -0
- package/skills/vueuse-functions/references/useDropZone.md +83 -0
- package/skills/vueuse-functions/references/useElementBounding.md +131 -0
- package/skills/vueuse-functions/references/useElementByPoint.md +48 -0
- package/skills/vueuse-functions/references/useElementHover.md +79 -0
- package/skills/vueuse-functions/references/useElementSize.md +78 -0
- package/skills/vueuse-functions/references/useElementVisibility.md +123 -0
- package/skills/vueuse-functions/references/useEventBus.md +101 -0
- package/skills/vueuse-functions/references/useEventListener.md +226 -0
- package/skills/vueuse-functions/references/useEventSource.md +204 -0
- package/skills/vueuse-functions/references/useExtractedObservable.md +198 -0
- package/skills/vueuse-functions/references/useEyeDropper.md +71 -0
- package/skills/vueuse-functions/references/useFavicon.md +67 -0
- package/skills/vueuse-functions/references/useFetch.md +546 -0
- package/skills/vueuse-functions/references/useFileDialog.md +91 -0
- package/skills/vueuse-functions/references/useFileSystemAccess.md +162 -0
- package/skills/vueuse-functions/references/useFirestore.md +129 -0
- package/skills/vueuse-functions/references/useFloor.md +31 -0
- package/skills/vueuse-functions/references/useFocus.md +99 -0
- package/skills/vueuse-functions/references/useFocusTrap.md +245 -0
- package/skills/vueuse-functions/references/useFocusWithin.md +57 -0
- package/skills/vueuse-functions/references/useFps.md +28 -0
- package/skills/vueuse-functions/references/useFullscreen.md +75 -0
- package/skills/vueuse-functions/references/useFuse.md +107 -0
- package/skills/vueuse-functions/references/useGamepad.md +222 -0
- package/skills/vueuse-functions/references/useGeolocation.md +85 -0
- package/skills/vueuse-functions/references/useIDBKeyval.md +93 -0
- package/skills/vueuse-functions/references/useIdle.md +88 -0
- package/skills/vueuse-functions/references/useImage.md +86 -0
- package/skills/vueuse-functions/references/useInfiniteScroll.md +157 -0
- package/skills/vueuse-functions/references/useIntersectionObserver.md +118 -0
- package/skills/vueuse-functions/references/useInterval.md +112 -0
- package/skills/vueuse-functions/references/useIntervalFn.md +50 -0
- package/skills/vueuse-functions/references/useIpcRenderer.md +144 -0
- package/skills/vueuse-functions/references/useIpcRendererInvoke.md +58 -0
- package/skills/vueuse-functions/references/useIpcRendererOn.md +52 -0
- package/skills/vueuse-functions/references/useJwt.md +57 -0
- package/skills/vueuse-functions/references/useKeyModifier.md +87 -0
- package/skills/vueuse-functions/references/useLastChanged.md +63 -0
- package/skills/vueuse-functions/references/useLocalStorage.md +41 -0
- package/skills/vueuse-functions/references/useMagicKeys.md +245 -0
- package/skills/vueuse-functions/references/useManualRefHistory.md +204 -0
- package/skills/vueuse-functions/references/useMath.md +47 -0
- package/skills/vueuse-functions/references/useMax.md +36 -0
- package/skills/vueuse-functions/references/useMediaControls.md +571 -0
- package/skills/vueuse-functions/references/useMediaQuery.md +53 -0
- package/skills/vueuse-functions/references/useMemoize.md +175 -0
- package/skills/vueuse-functions/references/useMemory.md +71 -0
- package/skills/vueuse-functions/references/useMin.md +36 -0
- package/skills/vueuse-functions/references/useMounted.md +38 -0
- package/skills/vueuse-functions/references/useMouse.md +113 -0
- package/skills/vueuse-functions/references/useMouseInElement.md +123 -0
- package/skills/vueuse-functions/references/useMousePressed.md +112 -0
- package/skills/vueuse-functions/references/useMutationObserver.md +61 -0
- package/skills/vueuse-functions/references/useNProgress.md +78 -0
- package/skills/vueuse-functions/references/useNavigatorLanguage.md +57 -0
- package/skills/vueuse-functions/references/useNetwork.md +106 -0
- package/skills/vueuse-functions/references/useNow.md +79 -0
- package/skills/vueuse-functions/references/useObjectUrl.md +55 -0
- package/skills/vueuse-functions/references/useObservable.md +91 -0
- package/skills/vueuse-functions/references/useOffsetPagination.md +199 -0
- package/skills/vueuse-functions/references/useOnline.md +41 -0
- package/skills/vueuse-functions/references/usePageLeave.md +42 -0
- package/skills/vueuse-functions/references/useParallax.md +58 -0
- package/skills/vueuse-functions/references/useParentElement.md +54 -0
- package/skills/vueuse-functions/references/usePerformanceObserver.md +48 -0
- package/skills/vueuse-functions/references/usePermission.md +79 -0
- package/skills/vueuse-functions/references/usePointer.md +89 -0
- package/skills/vueuse-functions/references/usePointerLock.md +60 -0
- package/skills/vueuse-functions/references/usePointerSwipe.md +80 -0
- package/skills/vueuse-functions/references/usePrecision.md +49 -0
- package/skills/vueuse-functions/references/usePreferredColorScheme.md +42 -0
- package/skills/vueuse-functions/references/usePreferredContrast.md +42 -0
- package/skills/vueuse-functions/references/usePreferredDark.md +41 -0
- package/skills/vueuse-functions/references/usePreferredLanguages.md +41 -0
- package/skills/vueuse-functions/references/usePreferredReducedMotion.md +42 -0
- package/skills/vueuse-functions/references/usePreferredReducedTransparency.md +42 -0
- package/skills/vueuse-functions/references/usePrevious.md +40 -0
- package/skills/vueuse-functions/references/useProjection.md +38 -0
- package/skills/vueuse-functions/references/useQRCode.md +53 -0
- package/skills/vueuse-functions/references/useRTDB.md +83 -0
- package/skills/vueuse-functions/references/useRafFn.md +68 -0
- package/skills/vueuse-functions/references/useRefHistory.md +285 -0
- package/skills/vueuse-functions/references/useResizeObserver.md +109 -0
- package/skills/vueuse-functions/references/useRound.md +31 -0
- package/skills/vueuse-functions/references/useRouteHash.md +27 -0
- package/skills/vueuse-functions/references/useRouteParams.md +38 -0
- package/skills/vueuse-functions/references/useRouteQuery.md +79 -0
- package/skills/vueuse-functions/references/useSSRWidth.md +47 -0
- package/skills/vueuse-functions/references/useScreenOrientation.md +96 -0
- package/skills/vueuse-functions/references/useScreenSafeArea.md +60 -0
- package/skills/vueuse-functions/references/useScriptTag.md +116 -0
- package/skills/vueuse-functions/references/useScroll.md +238 -0
- package/skills/vueuse-functions/references/useScrollLock.md +66 -0
- package/skills/vueuse-functions/references/useSessionStorage.md +41 -0
- package/skills/vueuse-functions/references/useShare.md +68 -0
- package/skills/vueuse-functions/references/useSortable.md +235 -0
- package/skills/vueuse-functions/references/useSorted.md +90 -0
- package/skills/vueuse-functions/references/useSpeechRecognition.md +94 -0
- package/skills/vueuse-functions/references/useSpeechSynthesis.md +105 -0
- package/skills/vueuse-functions/references/useStepper.md +137 -0
- package/skills/vueuse-functions/references/useStorage.md +278 -0
- package/skills/vueuse-functions/references/useStorageAsync.md +136 -0
- package/skills/vueuse-functions/references/useStyleTag.md +131 -0
- package/skills/vueuse-functions/references/useSubject.md +77 -0
- package/skills/vueuse-functions/references/useSubscription.md +33 -0
- package/skills/vueuse-functions/references/useSum.md +36 -0
- package/skills/vueuse-functions/references/useSupported.md +29 -0
- package/skills/vueuse-functions/references/useSwipe.md +75 -0
- package/skills/vueuse-functions/references/useTemplateRefsList.md +37 -0
- package/skills/vueuse-functions/references/useTextDirection.md +75 -0
- package/skills/vueuse-functions/references/useTextSelection.md +40 -0
- package/skills/vueuse-functions/references/useTextareaAutosize.md +97 -0
- package/skills/vueuse-functions/references/useThrottleFn.md +57 -0
- package/skills/vueuse-functions/references/useThrottledRefHistory.md +47 -0
- package/skills/vueuse-functions/references/useTimeAgo.md +154 -0
- package/skills/vueuse-functions/references/useTimeAgoIntl.md +117 -0
- package/skills/vueuse-functions/references/useTimeout.md +113 -0
- package/skills/vueuse-functions/references/useTimeoutFn.md +51 -0
- package/skills/vueuse-functions/references/useTimeoutPoll.md +47 -0
- package/skills/vueuse-functions/references/useTimestamp.md +89 -0
- package/skills/vueuse-functions/references/useTitle.md +113 -0
- package/skills/vueuse-functions/references/useToNumber.md +54 -0
- package/skills/vueuse-functions/references/useToString.md +34 -0
- package/skills/vueuse-functions/references/useToggle.md +103 -0
- package/skills/vueuse-functions/references/useTransition.md +265 -0
- package/skills/vueuse-functions/references/useTrunc.md +33 -0
- package/skills/vueuse-functions/references/useUrlSearchParams.md +121 -0
- package/skills/vueuse-functions/references/useUserMedia.md +1138 -0
- package/skills/vueuse-functions/references/useVModel.md +182 -0
- package/skills/vueuse-functions/references/useVModels.md +67 -0
- package/skills/vueuse-functions/references/useVibrate.md +87 -0
- package/skills/vueuse-functions/references/useVirtualList.md +182 -0
- package/skills/vueuse-functions/references/useWakeLock.md +50 -0
- package/skills/vueuse-functions/references/useWebNotification.md +176 -0
- package/skills/vueuse-functions/references/useWebSocket.md +299 -0
- package/skills/vueuse-functions/references/useWebWorker.md +60 -0
- package/skills/vueuse-functions/references/useWebWorkerFn.md +102 -0
- package/skills/vueuse-functions/references/useWindowFocus.md +46 -0
- package/skills/vueuse-functions/references/useWindowScroll.md +61 -0
- package/skills/vueuse-functions/references/useWindowSize.md +76 -0
- package/skills/vueuse-functions/references/useZoomFactor.md +53 -0
- package/skills/vueuse-functions/references/useZoomLevel.md +53 -0
- package/skills/vueuse-functions/references/watchArray.md +53 -0
- package/skills/vueuse-functions/references/watchAtMost.md +55 -0
- package/skills/vueuse-functions/references/watchDebounced.md +101 -0
- package/skills/vueuse-functions/references/watchDeep.md +54 -0
- package/skills/vueuse-functions/references/watchExtractedObservable.md +192 -0
- package/skills/vueuse-functions/references/watchIgnorable.md +120 -0
- package/skills/vueuse-functions/references/watchImmediate.md +44 -0
- package/skills/vueuse-functions/references/watchOnce.md +41 -0
- package/skills/vueuse-functions/references/watchPausable.md +86 -0
- package/skills/vueuse-functions/references/watchThrottled.md +108 -0
- package/skills/vueuse-functions/references/watchTriggerable.md +98 -0
- package/skills/vueuse-functions/references/watchWithFilter.md +54 -0
- package/skills/vueuse-functions/references/whenever.md +100 -0
- package/skills/web-design-guidelines/SKILL.md +39 -0
- package/skills/web-design-guidelines/SYNC.md +5 -0
- package/tsconfig.json +17 -0
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Configure Pinia Testing with createTestingPinia and setActivePinia
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: Missing Pinia configuration causes 'injection Symbol(pinia) not found' errors and failing tests
|
|
5
|
+
type: gotcha
|
|
6
|
+
tags: [vue3, testing, pinia, vitest, store, mocking, createTestingPinia]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Configure Pinia Testing with createTestingPinia and setActivePinia
|
|
10
|
+
|
|
11
|
+
**Impact: HIGH** - Testing components or composables that use Pinia stores without proper configuration results in "[Vue warn]: injection Symbol(pinia) not found" errors. Tests will fail or behave unexpectedly.
|
|
12
|
+
|
|
13
|
+
Use `@pinia/testing` package with `createTestingPinia` for component tests and `setActivePinia(createPinia())` for unit testing stores directly.
|
|
14
|
+
|
|
15
|
+
## Task Checklist
|
|
16
|
+
|
|
17
|
+
- [ ] Install `@pinia/testing` as a dev dependency
|
|
18
|
+
- [ ] Use `createTestingPinia` in component tests with `global.plugins`
|
|
19
|
+
- [ ] Use `setActivePinia(createPinia())` in `beforeEach` for store unit tests
|
|
20
|
+
- [ ] Configure `createSpy: vi.fn` when NOT using `globals: true` in Vitest
|
|
21
|
+
- [ ] Initialize store inside each test to get fresh state
|
|
22
|
+
- [ ] Use `stubActions: false` when you need real action execution
|
|
23
|
+
|
|
24
|
+
**Incorrect:**
|
|
25
|
+
```javascript
|
|
26
|
+
import { mount } from '@vue/test-utils'
|
|
27
|
+
import UserProfile from './UserProfile.vue'
|
|
28
|
+
|
|
29
|
+
// BAD: Missing Pinia - causes injection error
|
|
30
|
+
test('displays user name', () => {
|
|
31
|
+
const wrapper = mount(UserProfile) // ERROR: injection "Symbol(pinia)" not found
|
|
32
|
+
expect(wrapper.text()).toContain('John')
|
|
33
|
+
})
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
import { useUserStore } from '@/stores/user'
|
|
38
|
+
|
|
39
|
+
// BAD: No active Pinia instance
|
|
40
|
+
test('user store actions', () => {
|
|
41
|
+
const store = useUserStore() // ERROR: no active Pinia
|
|
42
|
+
store.login('john', 'password')
|
|
43
|
+
})
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Correct - Component Testing:**
|
|
47
|
+
```javascript
|
|
48
|
+
import { mount } from '@vue/test-utils'
|
|
49
|
+
import { createTestingPinia } from '@pinia/testing'
|
|
50
|
+
import { vi } from 'vitest'
|
|
51
|
+
import UserProfile from './UserProfile.vue'
|
|
52
|
+
import { useUserStore } from '@/stores/user'
|
|
53
|
+
|
|
54
|
+
// CORRECT: Provide testing pinia with stubbed actions
|
|
55
|
+
test('displays user name', () => {
|
|
56
|
+
const wrapper = mount(UserProfile, {
|
|
57
|
+
global: {
|
|
58
|
+
plugins: [
|
|
59
|
+
createTestingPinia({
|
|
60
|
+
createSpy: vi.fn, // Required if not using globals: true
|
|
61
|
+
initialState: {
|
|
62
|
+
user: { name: 'John', email: 'john@example.com' }
|
|
63
|
+
}
|
|
64
|
+
})
|
|
65
|
+
]
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
expect(wrapper.text()).toContain('John')
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
// CORRECT: Test with stubbed actions (default behavior)
|
|
73
|
+
test('calls logout action', async () => {
|
|
74
|
+
const wrapper = mount(UserProfile, {
|
|
75
|
+
global: {
|
|
76
|
+
plugins: [createTestingPinia({ createSpy: vi.fn })]
|
|
77
|
+
}
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
// Get store AFTER mounting with createTestingPinia
|
|
81
|
+
const store = useUserStore()
|
|
82
|
+
|
|
83
|
+
await wrapper.find('[data-testid="logout"]').trigger('click')
|
|
84
|
+
|
|
85
|
+
// Actions are stubbed and wrapped in spies
|
|
86
|
+
expect(store.logout).toHaveBeenCalled()
|
|
87
|
+
})
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Correct - Store Unit Testing:**
|
|
91
|
+
```javascript
|
|
92
|
+
import { describe, it, expect, beforeEach, vi } from 'vitest'
|
|
93
|
+
import { setActivePinia, createPinia } from 'pinia'
|
|
94
|
+
import { useUserStore } from '@/stores/user'
|
|
95
|
+
|
|
96
|
+
describe('User Store', () => {
|
|
97
|
+
beforeEach(() => {
|
|
98
|
+
// Create fresh Pinia instance for each test
|
|
99
|
+
setActivePinia(createPinia())
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
it('initializes with empty user', () => {
|
|
103
|
+
const store = useUserStore()
|
|
104
|
+
expect(store.user).toBeNull()
|
|
105
|
+
expect(store.isLoggedIn).toBe(false)
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('updates user on login', async () => {
|
|
109
|
+
const store = useUserStore()
|
|
110
|
+
|
|
111
|
+
// Real action executes - not stubbed
|
|
112
|
+
await store.login('john', 'password')
|
|
113
|
+
|
|
114
|
+
expect(store.user).toEqual({ name: 'John' })
|
|
115
|
+
expect(store.isLoggedIn).toBe(true)
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
it('clears user on logout', () => {
|
|
119
|
+
const store = useUserStore()
|
|
120
|
+
store.user = { name: 'John' } // Set initial state
|
|
121
|
+
|
|
122
|
+
store.logout()
|
|
123
|
+
|
|
124
|
+
expect(store.user).toBeNull()
|
|
125
|
+
})
|
|
126
|
+
})
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Testing with Real Actions vs Stubbed Actions
|
|
130
|
+
|
|
131
|
+
```javascript
|
|
132
|
+
import { createTestingPinia } from '@pinia/testing'
|
|
133
|
+
|
|
134
|
+
// Stubbed actions (default) - for isolation
|
|
135
|
+
const wrapper = mount(Component, {
|
|
136
|
+
global: {
|
|
137
|
+
plugins: [
|
|
138
|
+
createTestingPinia({
|
|
139
|
+
createSpy: vi.fn,
|
|
140
|
+
// stubActions: true (default) - actions are mocked
|
|
141
|
+
})
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
// Real actions - for integration testing
|
|
147
|
+
const wrapper = mount(Component, {
|
|
148
|
+
global: {
|
|
149
|
+
plugins: [
|
|
150
|
+
createTestingPinia({
|
|
151
|
+
createSpy: vi.fn,
|
|
152
|
+
stubActions: false // Actions execute normally
|
|
153
|
+
})
|
|
154
|
+
]
|
|
155
|
+
}
|
|
156
|
+
})
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Mocking Specific Action Implementations
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
import { mount } from '@vue/test-utils'
|
|
163
|
+
import { createTestingPinia } from '@pinia/testing'
|
|
164
|
+
import { vi } from 'vitest'
|
|
165
|
+
import { useCartStore } from '@/stores/cart'
|
|
166
|
+
|
|
167
|
+
test('handles checkout failure', async () => {
|
|
168
|
+
const wrapper = mount(Checkout, {
|
|
169
|
+
global: {
|
|
170
|
+
plugins: [createTestingPinia({ createSpy: vi.fn })]
|
|
171
|
+
}
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
const cartStore = useCartStore()
|
|
175
|
+
|
|
176
|
+
// Mock specific action behavior
|
|
177
|
+
cartStore.checkout.mockRejectedValue(new Error('Payment failed'))
|
|
178
|
+
|
|
179
|
+
await wrapper.find('[data-testid="checkout"]').trigger('click')
|
|
180
|
+
await flushPromises()
|
|
181
|
+
|
|
182
|
+
expect(wrapper.find('.error').text()).toContain('Payment failed')
|
|
183
|
+
})
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Spying on Actions with vi.spyOn
|
|
187
|
+
|
|
188
|
+
```javascript
|
|
189
|
+
import { setActivePinia, createPinia } from 'pinia'
|
|
190
|
+
import { vi } from 'vitest'
|
|
191
|
+
import { useUserStore } from '@/stores/user'
|
|
192
|
+
|
|
193
|
+
test('tracks action calls', async () => {
|
|
194
|
+
setActivePinia(createPinia())
|
|
195
|
+
const store = useUserStore()
|
|
196
|
+
|
|
197
|
+
const loginSpy = vi.spyOn(store, 'login')
|
|
198
|
+
loginSpy.mockResolvedValue({ success: true })
|
|
199
|
+
|
|
200
|
+
await store.login('john', 'password')
|
|
201
|
+
|
|
202
|
+
expect(loginSpy).toHaveBeenCalledWith('john', 'password')
|
|
203
|
+
})
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Testing Store $subscribe
|
|
207
|
+
|
|
208
|
+
```javascript
|
|
209
|
+
import { setActivePinia, createPinia } from 'pinia'
|
|
210
|
+
import { useUserStore } from '@/stores/user'
|
|
211
|
+
|
|
212
|
+
test('subscription triggers on state change', () => {
|
|
213
|
+
setActivePinia(createPinia())
|
|
214
|
+
const store = useUserStore()
|
|
215
|
+
|
|
216
|
+
const callback = vi.fn()
|
|
217
|
+
store.$subscribe(callback)
|
|
218
|
+
|
|
219
|
+
store.user = { name: 'John' }
|
|
220
|
+
|
|
221
|
+
expect(callback).toHaveBeenCalled()
|
|
222
|
+
})
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Reference
|
|
226
|
+
- [Pinia Testing Guide](https://pinia.vuejs.org/cookbook/testing.html)
|
|
227
|
+
- [@pinia/testing Package](https://www.npmjs.com/package/@pinia/testing)
|
|
228
|
+
- [Vue Test Utils - Plugins](https://test-utils.vuejs.org/guide/advanced/plugins.html)
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Wrap Async Setup Components in Suspense for Testing
|
|
3
|
+
impact: HIGH
|
|
4
|
+
impactDescription: Components with async setup() fail to render in tests without Suspense wrapper, causing cryptic errors
|
|
5
|
+
type: gotcha
|
|
6
|
+
tags: [vue3, testing, suspense, async-setup, vue-test-utils, vitest]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Wrap Async Setup Components in Suspense for Testing
|
|
10
|
+
|
|
11
|
+
**Impact: HIGH** - Components using `async setup()` require a `<Suspense>` wrapper to function correctly. Testing them without Suspense causes the component to never render, leading to test failures and confusing errors.
|
|
12
|
+
|
|
13
|
+
Create a test wrapper component with Suspense or use a `mountSuspense` helper function for testing async components.
|
|
14
|
+
|
|
15
|
+
## Task Checklist
|
|
16
|
+
|
|
17
|
+
- [ ] Identify components with async setup (uses `await` in `<script setup>` or `async setup()`)
|
|
18
|
+
- [ ] Create a wrapper component with `<Suspense>` for testing
|
|
19
|
+
- [ ] Use `flushPromises()` after mounting to wait for async resolution
|
|
20
|
+
- [ ] Access the actual component via `findComponent()` for assertions
|
|
21
|
+
- [ ] Consider using `@testing-library/vue` with caution (has Suspense issues)
|
|
22
|
+
|
|
23
|
+
**Incorrect:**
|
|
24
|
+
```javascript
|
|
25
|
+
import { mount } from '@vue/test-utils'
|
|
26
|
+
import AsyncUserProfile from './AsyncUserProfile.vue'
|
|
27
|
+
|
|
28
|
+
// BAD: Async component without Suspense wrapper
|
|
29
|
+
test('displays user data', async () => {
|
|
30
|
+
// This won't render - Vue expects Suspense wrapper for async setup
|
|
31
|
+
const wrapper = mount(AsyncUserProfile, {
|
|
32
|
+
props: { userId: 1 }
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
await flushPromises()
|
|
36
|
+
|
|
37
|
+
// This fails - component never rendered
|
|
38
|
+
expect(wrapper.find('.username').text()).toBe('John')
|
|
39
|
+
})
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Correct - Manual Wrapper Component:**
|
|
43
|
+
```javascript
|
|
44
|
+
import { mount, flushPromises } from '@vue/test-utils'
|
|
45
|
+
import { defineComponent, Suspense } from 'vue'
|
|
46
|
+
import AsyncUserProfile from './AsyncUserProfile.vue'
|
|
47
|
+
|
|
48
|
+
test('displays user data', async () => {
|
|
49
|
+
// Create wrapper component with Suspense
|
|
50
|
+
const TestWrapper = defineComponent({
|
|
51
|
+
components: { AsyncUserProfile },
|
|
52
|
+
template: `
|
|
53
|
+
<Suspense>
|
|
54
|
+
<AsyncUserProfile :user-id="1" />
|
|
55
|
+
<template #fallback>Loading...</template>
|
|
56
|
+
</Suspense>
|
|
57
|
+
`
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const wrapper = mount(TestWrapper)
|
|
61
|
+
|
|
62
|
+
// Initially shows fallback
|
|
63
|
+
expect(wrapper.text()).toContain('Loading...')
|
|
64
|
+
|
|
65
|
+
// Wait for async setup to complete
|
|
66
|
+
await flushPromises()
|
|
67
|
+
|
|
68
|
+
// Find the actual component for detailed assertions
|
|
69
|
+
const profile = wrapper.findComponent(AsyncUserProfile)
|
|
70
|
+
expect(profile.find('.username').text()).toBe('John')
|
|
71
|
+
})
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Correct - Reusable Helper Function:**
|
|
75
|
+
```javascript
|
|
76
|
+
// test-utils.js
|
|
77
|
+
import { mount, flushPromises } from '@vue/test-utils'
|
|
78
|
+
import { defineComponent, Suspense, h } from 'vue'
|
|
79
|
+
|
|
80
|
+
export async function mountSuspense(component, options = {}) {
|
|
81
|
+
const { props, slots, ...mountOptions } = options
|
|
82
|
+
|
|
83
|
+
const wrapper = mount(
|
|
84
|
+
defineComponent({
|
|
85
|
+
render() {
|
|
86
|
+
return h(
|
|
87
|
+
Suspense,
|
|
88
|
+
null,
|
|
89
|
+
{
|
|
90
|
+
default: () => h(component, props, slots),
|
|
91
|
+
fallback: () => h('div', 'Loading...')
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
}),
|
|
96
|
+
mountOptions
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
// Wait for async component to resolve
|
|
100
|
+
await flushPromises()
|
|
101
|
+
|
|
102
|
+
return {
|
|
103
|
+
wrapper,
|
|
104
|
+
// Provide easy access to the actual component
|
|
105
|
+
component: wrapper.findComponent(component)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
// AsyncUserProfile.test.js
|
|
112
|
+
import { mountSuspense } from './test-utils'
|
|
113
|
+
import AsyncUserProfile from './AsyncUserProfile.vue'
|
|
114
|
+
|
|
115
|
+
test('displays user data', async () => {
|
|
116
|
+
const { component } = await mountSuspense(AsyncUserProfile, {
|
|
117
|
+
props: { userId: 1 },
|
|
118
|
+
global: {
|
|
119
|
+
stubs: {
|
|
120
|
+
// Stub any child components if needed
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
expect(component.find('.username').text()).toBe('John')
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
test('handles errors gracefully', async () => {
|
|
129
|
+
const { component } = await mountSuspense(AsyncUserProfile, {
|
|
130
|
+
props: { userId: 'invalid' }
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
expect(component.find('.error').exists()).toBe(true)
|
|
134
|
+
})
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Testing with onErrorCaptured
|
|
138
|
+
|
|
139
|
+
```javascript
|
|
140
|
+
import { mount, flushPromises } from '@vue/test-utils'
|
|
141
|
+
import { defineComponent, Suspense, h, ref, onErrorCaptured } from 'vue'
|
|
142
|
+
import AsyncComponent from './AsyncComponent.vue'
|
|
143
|
+
|
|
144
|
+
test('catches async errors', async () => {
|
|
145
|
+
const capturedError = ref(null)
|
|
146
|
+
|
|
147
|
+
const TestWrapper = defineComponent({
|
|
148
|
+
setup() {
|
|
149
|
+
onErrorCaptured((error) => {
|
|
150
|
+
capturedError.value = error
|
|
151
|
+
return true // Prevent error propagation
|
|
152
|
+
})
|
|
153
|
+
return { capturedError }
|
|
154
|
+
},
|
|
155
|
+
render() {
|
|
156
|
+
return h(Suspense, null, {
|
|
157
|
+
default: () => h(AsyncComponent, { shouldFail: true }),
|
|
158
|
+
fallback: () => h('div', 'Loading...')
|
|
159
|
+
})
|
|
160
|
+
}
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
const wrapper = mount(TestWrapper)
|
|
164
|
+
await flushPromises()
|
|
165
|
+
|
|
166
|
+
expect(capturedError.value).toBeTruthy()
|
|
167
|
+
expect(capturedError.value.message).toContain('Failed to load')
|
|
168
|
+
})
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Using with Nuxt's mountSuspended
|
|
172
|
+
|
|
173
|
+
```javascript
|
|
174
|
+
// If using Nuxt, use the built-in mountSuspended helper
|
|
175
|
+
import { mountSuspended } from '@nuxt/test-utils/runtime'
|
|
176
|
+
import AsyncPage from './AsyncPage.vue'
|
|
177
|
+
|
|
178
|
+
test('renders async page', async () => {
|
|
179
|
+
const wrapper = await mountSuspended(AsyncPage, {
|
|
180
|
+
props: { id: 1 }
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
expect(wrapper.find('h1').text()).toBe('Page Title')
|
|
184
|
+
})
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
## Important Caveats
|
|
188
|
+
|
|
189
|
+
### @testing-library/vue Limitation
|
|
190
|
+
```javascript
|
|
191
|
+
// CAUTION: @testing-library/vue has issues with Suspense
|
|
192
|
+
// Use @vue/test-utils for async components instead
|
|
193
|
+
|
|
194
|
+
// If you must use Testing Library, create manual wrapper:
|
|
195
|
+
import { render, waitFor } from '@testing-library/vue'
|
|
196
|
+
|
|
197
|
+
test('async component with testing library', async () => {
|
|
198
|
+
const TestWrapper = {
|
|
199
|
+
template: `
|
|
200
|
+
<Suspense>
|
|
201
|
+
<AsyncComponent />
|
|
202
|
+
</Suspense>
|
|
203
|
+
`,
|
|
204
|
+
components: { AsyncComponent }
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const { getByText } = render(TestWrapper)
|
|
208
|
+
|
|
209
|
+
await waitFor(() => {
|
|
210
|
+
expect(getByText('Loaded content')).toBeInTheDocument()
|
|
211
|
+
})
|
|
212
|
+
})
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Accessing Component Instance
|
|
216
|
+
```javascript
|
|
217
|
+
test('access vm on async component', async () => {
|
|
218
|
+
const { wrapper, component } = await mountSuspense(AsyncComponent)
|
|
219
|
+
|
|
220
|
+
// The wrapper.vm is the Suspense wrapper - not useful
|
|
221
|
+
// Use component.vm for the actual async component
|
|
222
|
+
expect(component.vm.someData).toBe('value')
|
|
223
|
+
})
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## Reference
|
|
227
|
+
- [Vue Test Utils - Async Suspense](https://test-utils.vuejs.org/guide/advanced/async-suspense)
|
|
228
|
+
- [Vue.js Suspense Documentation](https://vuejs.org/guide/built-ins/suspense.html)
|
|
229
|
+
- [Testing Library Vue Suspense Issue](https://github.com/testing-library/vue-testing-library/issues/230)
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Use Vitest for Vue 3 Testing - Recommended by Vue Team
|
|
3
|
+
impact: MEDIUM
|
|
4
|
+
impactDescription: Using Jest or other runners with Vite projects requires complex configuration and causes slower test runs
|
|
5
|
+
type: best-practice
|
|
6
|
+
tags: [vue3, testing, vitest, vite, configuration, setup]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Use Vitest for Vue 3 Testing - Recommended by Vue Team
|
|
10
|
+
|
|
11
|
+
**Impact: MEDIUM** - Vitest is created and maintained by Vue/Vite team members and shares the same configuration and transform pipeline as Vite. Using Jest or other test runners with Vite-based projects requires additional configuration and can result in slower test execution and compatibility issues.
|
|
12
|
+
|
|
13
|
+
Use Vitest for new Vue 3 projects. Only consider Jest if migrating an existing test suite.
|
|
14
|
+
|
|
15
|
+
## Task Checklist
|
|
16
|
+
|
|
17
|
+
- [ ] Install Vitest and related packages for Vue testing
|
|
18
|
+
- [ ] Configure vitest in vite.config.js or vitest.config.js
|
|
19
|
+
- [ ] Set up proper test environment (happy-dom or jsdom)
|
|
20
|
+
- [ ] Add test scripts to package.json
|
|
21
|
+
- [ ] Configure globals if desired for cleaner test syntax
|
|
22
|
+
- [ ] Use @vue/test-utils for component mounting
|
|
23
|
+
|
|
24
|
+
## Quick Setup
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Install required packages
|
|
28
|
+
npm install -D vitest @vue/test-utils happy-dom
|
|
29
|
+
# or with jsdom
|
|
30
|
+
npm install -D vitest @vue/test-utils jsdom
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
**vite.config.js:**
|
|
34
|
+
```javascript
|
|
35
|
+
import { defineConfig } from 'vite'
|
|
36
|
+
import vue from '@vitejs/plugin-vue'
|
|
37
|
+
|
|
38
|
+
export default defineConfig({
|
|
39
|
+
plugins: [vue()],
|
|
40
|
+
test: {
|
|
41
|
+
// Enable global test APIs (describe, it, expect)
|
|
42
|
+
globals: true,
|
|
43
|
+
// Use happy-dom for faster tests (or 'jsdom' for better compatibility)
|
|
44
|
+
environment: 'happy-dom',
|
|
45
|
+
// Optional: Setup files for global configuration
|
|
46
|
+
setupFiles: ['./src/test/setup.js']
|
|
47
|
+
}
|
|
48
|
+
})
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**package.json:**
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"scripts": {
|
|
55
|
+
"test": "vitest",
|
|
56
|
+
"test:run": "vitest run",
|
|
57
|
+
"test:coverage": "vitest run --coverage"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**tsconfig.json (if using TypeScript):**
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"compilerOptions": {
|
|
66
|
+
"types": ["vitest/globals"]
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Test File Example
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
// src/components/Counter.test.js
|
|
75
|
+
import { describe, it, expect, beforeEach } from 'vitest' // optional with globals: true
|
|
76
|
+
import { mount } from '@vue/test-utils'
|
|
77
|
+
import Counter from './Counter.vue'
|
|
78
|
+
|
|
79
|
+
describe('Counter', () => {
|
|
80
|
+
let wrapper
|
|
81
|
+
|
|
82
|
+
beforeEach(() => {
|
|
83
|
+
wrapper = mount(Counter)
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
it('renders initial count', () => {
|
|
87
|
+
expect(wrapper.find('[data-testid="count"]').text()).toBe('0')
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
it('increments when button clicked', async () => {
|
|
91
|
+
await wrapper.find('[data-testid="increment"]').trigger('click')
|
|
92
|
+
expect(wrapper.find('[data-testid="count"]').text()).toBe('1')
|
|
93
|
+
})
|
|
94
|
+
})
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Vitest vs Jest Comparison
|
|
98
|
+
|
|
99
|
+
| Feature | Vitest | Jest |
|
|
100
|
+
|---------|--------|------|
|
|
101
|
+
| Vite Integration | Native | Requires config |
|
|
102
|
+
| Speed | Very fast (ESM native) | Slower with Vite |
|
|
103
|
+
| Watch Mode | Excellent | Good |
|
|
104
|
+
| Vue SFC Support | Works with Vite | Needs vue-jest |
|
|
105
|
+
| Config Sharing | Same as vite.config | Separate |
|
|
106
|
+
| API | Jest-compatible | Standard |
|
|
107
|
+
|
|
108
|
+
## Using with Testing Library
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
npm install -D @testing-library/vue @testing-library/jest-dom
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
```javascript
|
|
115
|
+
// src/test/setup.js
|
|
116
|
+
import { expect } from 'vitest'
|
|
117
|
+
import * as matchers from '@testing-library/jest-dom/matchers'
|
|
118
|
+
|
|
119
|
+
expect.extend(matchers)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
```javascript
|
|
123
|
+
// Component.test.js
|
|
124
|
+
import { render, screen, fireEvent } from '@testing-library/vue'
|
|
125
|
+
import UserCard from './UserCard.vue'
|
|
126
|
+
|
|
127
|
+
test('displays user name', () => {
|
|
128
|
+
render(UserCard, {
|
|
129
|
+
props: { name: 'John Doe' }
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
expect(screen.getByText('John Doe')).toBeInTheDocument()
|
|
133
|
+
})
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Advanced Configuration
|
|
137
|
+
|
|
138
|
+
```javascript
|
|
139
|
+
// vitest.config.js (separate file if preferred)
|
|
140
|
+
import { defineConfig } from 'vitest/config'
|
|
141
|
+
import vue from '@vitejs/plugin-vue'
|
|
142
|
+
|
|
143
|
+
export default defineConfig({
|
|
144
|
+
plugins: [vue()],
|
|
145
|
+
test: {
|
|
146
|
+
globals: true,
|
|
147
|
+
environment: 'happy-dom',
|
|
148
|
+
include: ['**/*.{test,spec}.{js,ts,jsx,tsx}'],
|
|
149
|
+
exclude: ['node_modules', 'dist', 'e2e'],
|
|
150
|
+
coverage: {
|
|
151
|
+
provider: 'v8',
|
|
152
|
+
reporter: ['text', 'json', 'html'],
|
|
153
|
+
exclude: ['node_modules', 'test']
|
|
154
|
+
},
|
|
155
|
+
// Helpful for debugging
|
|
156
|
+
reporters: ['verbose'],
|
|
157
|
+
// Run tests in sequence in CI
|
|
158
|
+
poolOptions: {
|
|
159
|
+
threads: {
|
|
160
|
+
singleThread: process.env.CI === 'true'
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
})
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Common Patterns
|
|
168
|
+
|
|
169
|
+
### Mocking Modules
|
|
170
|
+
```javascript
|
|
171
|
+
import { vi } from 'vitest'
|
|
172
|
+
|
|
173
|
+
vi.mock('@/api/users', () => ({
|
|
174
|
+
fetchUser: vi.fn().mockResolvedValue({ name: 'John' })
|
|
175
|
+
}))
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Testing with Fake Timers
|
|
179
|
+
```javascript
|
|
180
|
+
import { vi, beforeEach, afterEach } from 'vitest'
|
|
181
|
+
|
|
182
|
+
beforeEach(() => {
|
|
183
|
+
vi.useFakeTimers()
|
|
184
|
+
})
|
|
185
|
+
|
|
186
|
+
afterEach(() => {
|
|
187
|
+
vi.restoreAllMocks()
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
test('debounced search', async () => {
|
|
191
|
+
const wrapper = mount(SearchBox)
|
|
192
|
+
await wrapper.find('input').setValue('vue')
|
|
193
|
+
|
|
194
|
+
vi.advanceTimersByTime(300)
|
|
195
|
+
await flushPromises()
|
|
196
|
+
|
|
197
|
+
expect(wrapper.emitted('search')).toBeTruthy()
|
|
198
|
+
})
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
## Reference
|
|
202
|
+
- [Vitest Documentation](https://vitest.dev/)
|
|
203
|
+
- [Vue.js Testing Guide](https://vuejs.org/guide/scaling-up/testing)
|
|
204
|
+
- [Vue Test Utils](https://test-utils.vuejs.org/)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019-PRESENT Anthony Fu<https://github.com/antfu>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|