diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 6bb15f5cc..000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,36 +0,0 @@ -module.exports = { - env: { - node: true - }, - extends: [ - 'prettier', - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended' - ], - parser: '@typescript-eslint/parser', - parserOptions: { - ecmaVersion: 'latest', - sourceType: 'module' - }, - plugins: ['prettier', '@typescript-eslint'], - rules: { - 'prettier/prettier': ['error'], - '@typescript-eslint/no-extra-semi': 'off', - 'no-restricted-imports': [ - 'error', - { - patterns: ['src/*'] - } - ], - - // Currently, disabled to avoid a lot of changes during migration - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-non-null-assertion': 'off', - '@typescript-eslint/no-unused-vars': 'off', - '@typescript-eslint/ban-types': 'off', - '@typescript-eslint/no-empty-function': 'off', - '@typescript-eslint/ban-ts-comment': 'off', - 'prefer-const': 'off', - 'no-prototype-builtins': 'off' - } -} diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml new file mode 100644 index 000000000..67bf729cf --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug-report.yml @@ -0,0 +1,50 @@ +name: Bug report +description: Create a report to help us improve +labels: ['bug'] +title: 'Bug: ' +type: 'Bug' +body: + - type: markdown + attributes: + value: | + Thanks for your interest in the project! We appreciate bugs filed and PRs submitted! + + Please use a template below to create a minimal reproduction + 👉 https://stackblitz.com/github/vuejs/create-vue-templates/tree/main/typescript-vitest?file=src%2Fcomponents%2F__tests__%2FHelloWorld.spec.ts + + For test-utils v1 and Vue v2, please report at: + 👉 https://github.com/vuejs/vue-test-utils + - type: textarea + id: description + attributes: + label: Describe the bug + description: A clear and concise description of what the bug is. + validations: + required: true + - type: input + id: reproduction + attributes: + label: Reproduction + placeholder: https://stackblitz.com/... + validations: + required: true + - type: textarea + id: expected-behavior + attributes: + label: Expected behavior + description: A clear and concise description of what you expected to happen. + validations: + required: true + - type: textarea + id: environment + attributes: + label: Environment + placeholder: Environment + description: Output of `npx envinfo --system --npmPackages vue,@vue/test-utils,vitest,jest`. + validations: + required: true + - type: textarea + id: additional-context + attributes: + label: Additional context + description: Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 11022ce50..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: 'Bug: ' -labels: bug -assignees: '' - ---- - - - - -**Describe the bug** - - -**To Reproduce** - - -**Expected behavior** - - -**Related information:** - - - -**Additional context** - diff --git a/.github/ISSUE_TEMPLATE/feature-requests.yml b/.github/ISSUE_TEMPLATE/feature-requests.yml new file mode 100644 index 000000000..3bbc903f0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature-requests.yml @@ -0,0 +1,33 @@ +name: Feature request +description: Suggest an idea for this project +type: Feature +title: 'Feature request: ' +body: + - type: markdown + attributes: + value: | + Thanks for your interest in the project – we appreciate your ideas! Please bear in mind that maintainers might need to request additional information or context before adding a new feature. They need to think about edge cases and how this feature fits in the codebase, so a feature request might take some time to move forward. + - type: textarea + id: feature-description + attributes: + label: Is your feature request related to a problem? Please describe. + description: A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + validations: + required: true + - type: textarea + id: feature-solution + attributes: + label: Describe the solution you'd like + description: A clear and concise description of what you want to happen. + validations: + required: true + - type: textarea + id: feature-alternatives + attributes: + label: Describe alternatives you've considered + description: A clear and concise description of any alternative solutions or features you've considered. + - type: textarea + id: feature-additional-context + attributes: + label: Additional context + description: Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 89a960818..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: 'Feature request:' -labels: '' -assignees: '' - ---- - - - - -**Is your feature request related to a problem? Please describe.** - - -**Describe the solution you'd like** - - -**Describe alternatives you've considered** - - -**Additional context** - diff --git a/.github/renovate.json5 b/.github/renovate.json5 index 32d9ec60a..b1c0e1356 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -1,12 +1,10 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", - "extends": ["config:base"], + "extends": ["config:js-lib"], // only 1 PR at the same time (to avoid cascading rebase) "prConcurrentLimit": 1, // auto-merge if build is OK "automerge": true, - // ignore js-beautify updates until https://github.com/vuejs/test-utils/pull/1834 is resolved - "ignoreDeps": ["js-beautify"], "packageRules": [ // group vitest packages update { diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f7a879a05..ca2974f75 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,16 +16,14 @@ jobs: strategy: matrix: - node: [16, 18] + node: [20, 22, 24] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v5 - name: Install pnpm - uses: pnpm/action-setup@v2.2.4 - with: - version: 8.6.3 + uses: pnpm/action-setup@v4.1.0 - name: Use Node.js ${{ matrix.node }} - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} cache: 'pnpm' @@ -37,3 +35,4 @@ jobs: - run: pnpm run test:build - run: pnpm run tsd - run: pnpm run vue-tsc + - run: pnpm run tsc:docs diff --git a/.gitignore b/.gitignore index 621d577e1..d1f75bfb8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ node_modules dist coverage +docs/.vitepress/cache diff --git a/README.md b/README.md index 6ce145f24..67522c817 100644 --- a/README.md +++ b/README.md @@ -25,63 +25,19 @@ See the [docs](https://test-utils.vuejs.org/). Get started by running `pnpm install`. You can run the tests with `pnpm test`. That's it! -## Comparison with Vue Test Utils v1 (targeting Vue 2) - -This is table for those coming from VTU 1, comparing the two APIs. Some things are still a work in progress. - -- ✅ - implemented -- ❌ - not yet implemented -- ⚰️ - will not be implemented (if you have a compelling use case, please open an issue) - -### Mounting Options - -| option | status | notes | -|------------------|--------|-----------------------------------------------------------------------------------| -| data | ✅ | -| slots | ✅ | -| mocks | ✅ | nested in `global` | -| propsData | ✅ | now called `props` | -| provide | ✅ | nested in `global` | -| mixins | ✅ | (new!) nested in `global` | -| plugins | ✅ | (new!) nested in `global` | -| component | ✅ | (new!) nested in `global` | -| directives | ✅ | (new!) nested in `global` | -| stubs | ✅ | -| attachToDocument | ✅ | renamed `attachTo`. See [here](https://github.com/vuejs/vue-test-utils/pull/1492) | -| attrs | ✅ | -| scopedSlots | ⚰️ | scopedSlots are merged with `slots` in Vue 3 | -| context | ⚰️ | different from Vue 2, does not make sense anymore. | -| localVue | ⚰️ | no longer required - Vue 3 there is no global Vue instance to mutate. | -| listeners | ⚰️ | no longer exists in Vue 3 | -| parentComponent | ⚰️ | - -### Wrapper API (mount) - -| method | status | notes | -|----------------|--------|-------------------------------------------------------------------------------------------------------------------------------------| -| attributes | ✅ | -| classes | ✅ | -| exists | ✅ | -| find | ✅ | only `querySelector` syntax is supported. `find(Comp)` under discussion [here](https://github.com/vuejs/vue-test-utils/issues/1498) | -| emitted | ✅ | -| findAll | ✅ | see above. `.vm` is different to Vue 2. We are exploring options. | -| get | ✅ | -| html | ✅ | -| setValue | ✅ | works for select, checkbox, radio button, input, textarea. Returns `nextTick`. | -| text | ✅ | -| trigger | ✅ | returns `nextTick`. You can do `await wrapper.find('button').trigger('click')` | -| setProps | ✅ | -| props | ✅ | -| setData | ✅ | -| destroy | ✅ | renamed to `unmount` to match Vue 3 lifecycle hook name. | -| props | ✅ | -| isVisible | ✅ | -| contains | ⚰️ | use `find` | -| emittedByOrder | ⚰️ | use `emitted` | -| setSelected | ⚰️ | now part of `setValue` | -| setChecked | ⚰️ | now part of `setValue` | -| is | ⚰️ | -| isEmpty | ⚰️ | use matchers such as [this](https://github.com/testing-library/jest-dom#tobeempty) | -| isVueInstance | ⚰️ | -| name | ⚰️ | -| setMethods | ⚰️ | +## Contributing Docs + +All the documentation files can be found in `docs`. It contains the English markdown files while translation(s) are stored in their corresponding `` sub-folder(s): + +- [`fr`](https://github.com/vuejs/test-utils/tree/main/docs/fr): French translation. + +Besides that, the `.vitepress` sub-folder contains the config and theme, including the i18n information. + +- `pnpm docs:dev`: Start the docs dev server. +- `pnpm docs:build`: Build the docs. + +To add or maintain the translations, we follow the [Vue Ecosystem Translation Guidelines](https://github.com/vuejs-translations/guidelines/blob/main/README_ECOSYSTEM.md). + +- `pnpm docs:translation:status []`: Show the translation status for your language. If you don't specify a language, it will show the status for all languages. +- `pnpm docs:translation:compare `: Compare the docs with the latest checkpoint for your language. +- `pnpm docs:translation:update []`: Update the checkpoint for your language. The checkpoint will be set by the latest commit hash. However, you can also specify a commit hash manually. diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts deleted file mode 100644 index 46c46d4e7..000000000 --- a/docs/.vitepress/config.ts +++ /dev/null @@ -1,235 +0,0 @@ -import { defineConfig } from 'vitepress'; -import { frLocaleConfig } from "../fr/.vitepress/locale-config"; - -export default defineConfig({ - title: `Vue Test Utils`, - description: 'The documentation for the official Vue Test Utils', - locales: { - "/": { - label: "English", - lang: 'en-US', - title: `Vue Test Utils` - }, - "/fr/": { - label: "Français", - title: "Vue Test Utils", - lang: "fr-FR", - description: "La documentation officielle de Vue Test Utils", - }, - }, - head: [['link', { rel: 'icon', href: `/logo.png` }]], - themeConfig: { - locales: { - "/": { - label: 'English', - selectText: 'Languages', - nav: [ - { text: 'Guide', link: '/guide/' }, - { text: 'API Reference', link: '/api/' }, - { text: 'Migrating from Vue 2', link: '/migration/' }, - { - text: 'Changelog', - link: 'https://github.com/vuejs/test-utils/releases' - } - ], - sidebar: [ - { - text: 'Installation', - link: '/installation/' - }, - { - text: 'Essentials', - collapsable: false, - children: [ - { text: 'Getting Started', link: '/guide/' }, - { text: 'A Crash Course', link: '/guide/essentials/a-crash-course' }, - { - text: 'Conditional Rendering', - link: '/guide/essentials/conditional-rendering' - }, - { - text: 'Testing Emitted Events', - link: '/guide/essentials/event-handling' - }, - { text: 'Testing Forms', link: '/guide/essentials/forms' }, - { - text: 'Passing Data to Components', - link: '/guide/essentials/passing-data' - }, - { - text: 'Write components that are easy to test', - link: '/guide/essentials/easy-to-test' - } - ] - }, - { - text: 'Vue Test Utils in depth', - collapsable: false, - children: [ - { text: 'Slots', link: '/guide/advanced/slots' }, - { - text: 'Asynchronous Behavior', - link: '/guide/advanced/async-suspense' - }, - { - text: 'Making HTTP Requests', - link: '/guide/advanced/http-requests' - }, - { text: 'Transitions', link: '/guide/advanced/transitions' }, - { - text: 'Component Instance', - link: '/guide/advanced/component-instance' - }, - { - text: 'Reusability and Composition', - link: '/guide/advanced/reusability-composition' - }, - { text: 'Testing v-model', link: '/guide/advanced/v-model' }, - { text: 'Testing Vuex', link: '/guide/advanced/vuex' }, - { text: 'Testing Vue Router', link: '/guide/advanced/vue-router' }, - { text: 'Testing Teleport', link: '/guide/advanced/teleport' }, - { - text: 'Stubs and Shallow Mount', - link: '/guide/advanced/stubs-shallow-mount' - }, - { text: 'Testing Server-side Rendering', link: '/guide/advanced/ssr' } - ] - }, - { - text: 'Extending Vue Test Utils', - collapsable: false, - children: [ - { text: 'Plugins', link: '/guide/extending-vtu/plugins' }, - { - text: 'Community and Learning', - link: '/guide/extending-vtu/community-learning' - } - ] - }, - { - text: 'FAQ', - link: '/guide/faq/' - }, - { - text: 'Migrating from Vue 2', - link: '/migration/' - }, - { - text: 'API Reference', - link: '/api/' - } - ] - }, - "/fr/": frLocaleConfig, - }, - repo: 'vuejs/test-utils', - docsRepo: 'vuejs/test-utils', - docsDir: 'docs', - docsBranch: 'main', - editLinks: true, - algolia: { - appId: 'BH4D9OD16A', - apiKey: 'ee1b8516c9e5a5be9b6c25684eafc42f', - indexName: 'vue_test_utils', - searchParameters: { - facetFilters: ['tags:next'] - } - }, - nav: [ - { text: 'Guide', link: '/guide/' }, - { text: 'API Reference', link: '/api/' }, - { text: 'Migrating from Vue 2', link: '/migration/' }, - { - text: 'Changelog', - link: 'https://github.com/vuejs/test-utils/releases' - } - ], - sidebar: [ - { - text: 'Installation', - link: '/installation/' - }, - { - text: 'Essentials', - collapsable: false, - children: [ - { text: 'Getting Started', link: '/guide/' }, - { text: 'A Crash Course', link: '/guide/essentials/a-crash-course' }, - { - text: 'Conditional Rendering', - link: '/guide/essentials/conditional-rendering' - }, - { - text: 'Testing Emitted Events', - link: '/guide/essentials/event-handling' - }, - { text: 'Testing Forms', link: '/guide/essentials/forms' }, - { - text: 'Passing Data to Components', - link: '/guide/essentials/passing-data' - }, - { - text: 'Write components that are easy to test', - link: '/guide/essentials/easy-to-test' - } - ] - }, - { - text: 'Vue Test Utils in depth', - collapsable: false, - children: [ - { text: 'Slots', link: '/guide/advanced/slots' }, - { - text: 'Asynchronous Behavior', - link: '/guide/advanced/async-suspense' - }, - { - text: 'Making HTTP Requests', - link: '/guide/advanced/http-requests' - }, - { text: 'Transitions', link: '/guide/advanced/transitions' }, - { - text: 'Component Instance', - link: '/guide/advanced/component-instance' - }, - { - text: 'Reusability and Composition', - link: '/guide/advanced/reusability-composition' - }, - { text: 'Testing v-model', link: '/guide/advanced/v-model' }, - { text: 'Testing Vuex', link: '/guide/advanced/vuex' }, - { text: 'Testing Vue Router', link: '/guide/advanced/vue-router' }, - { text: 'Testing Teleport', link: '/guide/advanced/teleport' }, - { - text: 'Stubs and Shallow Mount', - link: '/guide/advanced/stubs-shallow-mount' - }, - { text: 'Server-side rendering', link: '/guide/advanced/ssr' } - ] - }, - { - text: 'Extending Vue Test Utils', - collapsable: false, - children: [ - { text: 'Plugins', link: '/guide/extending-vtu/plugins' }, - { - text: 'Community and Learning', - link: '/guide/extending-vtu/community-learning' - } - ] - }, - { - text: 'FAQ', - link: '/guide/faq/' - }, - { - text: 'Migrating from Vue 2', - link: '/migration/' - }, - { - text: 'API Reference', - link: '/api/' - } - ] - } -}) diff --git a/docs/.vitepress/config/en.mts b/docs/.vitepress/config/en.mts new file mode 100644 index 000000000..f0e553066 --- /dev/null +++ b/docs/.vitepress/config/en.mts @@ -0,0 +1,121 @@ +import type { DefaultTheme, LocaleSpecificConfig } from 'vitepress' + +export const META_URL = '' +export const META_TITLE = 'Vue Test Utils' +export const META_DESCRIPTION = 'The official testing suite utils for Vue.js 3' + +export const enConfig: LocaleSpecificConfig = { + description: META_DESCRIPTION, + head: [ + ['meta', { property: 'og:url', content: META_URL }], + ['meta', { property: 'og:title', content: META_TITLE }], + ['meta', { property: 'og:description', content: META_DESCRIPTION }], + ['meta', { property: 'twitter:url', content: META_URL }], + ['meta', { property: 'twitter:title', content: META_TITLE }], + ['meta', { property: 'twitter:description', content: META_DESCRIPTION }], + ], + + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/test-utils/edit/main/docs/:path', + text: 'Suggest changes to this page', + }, + + nav: [ + { text: 'Guide', link: '/guide/' }, + { text: 'API Reference', link: '/api/' }, + { text: 'Migrating from Vue 2', link: '/migration/' }, + { + text: 'Changelog', + link: 'https://github.com/vuejs/test-utils/releases' + } + ], + + sidebar: { + '/': [ + { + text: 'Installation', + link: '/installation/' + }, + { + text: 'Essentials', + items: [ + { text: 'Getting Started', link: '/guide/' }, + { text: 'A Crash Course', link: '/guide/essentials/a-crash-course' }, + { + text: 'Conditional Rendering', + link: '/guide/essentials/conditional-rendering' + }, + { + text: 'Testing Emitted Events', + link: '/guide/essentials/event-handling' + }, + { text: 'Testing Forms', link: '/guide/essentials/forms' }, + { + text: 'Passing Data to Components', + link: '/guide/essentials/passing-data' + }, + { + text: 'Write components that are easy to test', + link: '/guide/essentials/easy-to-test' + } + ] + }, + { + text: 'Vue Test Utils in depth', + items: [ + { text: 'Slots', link: '/guide/advanced/slots' }, + { + text: 'Asynchronous Behavior', + link: '/guide/advanced/async-suspense' + }, + { + text: 'Making HTTP Requests', + link: '/guide/advanced/http-requests' + }, + { text: 'Transitions', link: '/guide/advanced/transitions' }, + { + text: 'Component Instance', + link: '/guide/advanced/component-instance' + }, + { + text: 'Reusability and Composition', + link: '/guide/advanced/reusability-composition' + }, + { text: 'Testing v-model', link: '/guide/advanced/v-model' }, + { text: 'Testing Vuex', link: '/guide/advanced/vuex' }, + { text: 'Testing Vue Router', link: '/guide/advanced/vue-router' }, + { text: 'Testing Teleport', link: '/guide/advanced/teleport' }, + { + text: 'Stubs and Shallow Mount', + link: '/guide/advanced/stubs-shallow-mount' + }, + { text: 'Testing Server-side Rendering', link: '/guide/advanced/ssr' } + ] + }, + { + text: 'Extending Vue Test Utils', + items: [ + { text: 'Plugins', link: '/guide/extending-vtu/plugins' }, + { + text: 'Community and Learning', + link: '/guide/extending-vtu/community-learning' + } + ] + }, + { + text: 'FAQ', + link: '/guide/faq/' + }, + { + text: 'Migrating from Vue 2', + link: '/migration/' + }, + { + text: 'API Reference', + link: '/api/' + } + ] + } + } +} diff --git a/docs/.vitepress/config/fr.mts b/docs/.vitepress/config/fr.mts new file mode 100644 index 000000000..33ba5f222 --- /dev/null +++ b/docs/.vitepress/config/fr.mts @@ -0,0 +1,125 @@ +import type { DefaultTheme, LocaleSpecificConfig } from 'vitepress' + +export const META_URL = '' +export const META_TITLE = 'Vue Test Utils' +export const META_DESCRIPTION = 'La librairie officielle de tests unitaires pour Vue.js 3' + +export const frConfig: LocaleSpecificConfig = { + description: META_DESCRIPTION, + head: [ + ['meta', { property: 'og:url', content: META_URL }], + ['meta', { property: 'og:title', content: META_TITLE }], + ['meta', { property: 'og:description', content: META_DESCRIPTION }], + ['meta', { property: 'twitter:url', content: META_URL }], + ['meta', { property: 'twitter:title', content: META_TITLE }], + ['meta', { property: 'twitter:description', content: META_DESCRIPTION }], + ], + + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/test-utils/edit/main/docs/:path', + text: 'Suggest changes to this page', + }, + + nav: [ + { text: 'Guide', link: '/fr/guide/' }, + { text: 'API', link: '/fr/api/' }, + { + text: 'FAQ', + link: '/fr/guide/faq/' + }, + { text: 'Migrer depuis Vue 2', link: '/fr/migration/' }, + { + text: 'Journal de modifications', + link: 'https://github.com/vuejs/test-utils/releases' + } + ], + + sidebar: { + '/fr': [ + { + text: 'Installation', + link: '/fr/installation/' + }, + { + text: 'Les Bases', + items: [ + { text: 'Pour commencer', link: '/fr/guide/' }, + { text: 'Cours rapide', link: '/fr/guide/essentials/a-crash-course' }, + { + text: 'Rendu conditionnel', + link: '/fr/guide/essentials/conditional-rendering' + }, + { + text: 'Tester les évènements émis', + link: '/fr/guide/essentials/event-handling' + }, + { text: 'Tester les formulaires', link: '/fr/guide/essentials/forms' }, + { + text: 'Passer des données aux Composants', + link: '/fr/guide/essentials/passing-data' + }, + { + text: 'Écrire des composants facile à tester', + link: '/fr/guide/essentials/easy-to-test' + } + ] + }, + { + text: 'Vue Test Utils en détail', + items: [ + { text: 'Slots', link: '/fr/guide/advanced/slots' }, + { + text: 'Comportement asynchrone', + link: '/fr/guide/advanced/async-suspense' + }, + { + text: 'Faire des requêtes HTTP', + link: '/fr/guide/advanced/http-requests' + }, + { text: 'Transitions', link: '/fr/guide/advanced/transitions' }, + { + text: 'Instance de Composant', + link: '/fr/guide/advanced/component-instance' + }, + { + text: 'Réutilisabilité et Composition', + link: '/fr/guide/advanced/reusability-composition' + }, + { text: 'Tester v-model', link: '/fr/guide/advanced/v-model' }, + { text: 'Tester Vuex', link: '/fr/guide/advanced/vuex' }, + { text: 'Tester Vue Router', link: '/fr/guide/advanced/vue-router' }, + { text: 'Tester Teleport', link: '/fr/guide/advanced/teleport' }, + { + text: 'Composants de Substitution (Stubs) et Montage Partiel', + link: '/fr/guide/advanced/stubs-shallow-mount' + }, + { text: 'Tester le Rendu côté Serveur (SSR)', link: '/fr/guide/advanced/ssr' } + ] + }, + { + text: 'Extensions de Vue Test Utils', + items: [ + { text: 'Plugins', link: '/fr/guide/extending-vtu/plugins' }, + { + text: 'Communauté et Apprentissage', + link: '/fr/guide/extending-vtu/community-learning' + } + ] + }, + { + text: 'FAQ', + link: '/fr/guide/faq/' + }, + { + text: 'Migrer depuis Vue 2', + link: '/fr/migration/' + }, + { + text: 'API', + link: '/fr/api/' + } + ] + } + } +} diff --git a/docs/.vitepress/config/index.mts b/docs/.vitepress/config/index.mts new file mode 100644 index 000000000..ad9c16ffe --- /dev/null +++ b/docs/.vitepress/config/index.mts @@ -0,0 +1,15 @@ +import { enConfig } from './en.mts' +import { frConfig } from './fr.mts' +import { zhConfig } from './zh.mts' +import { sharedConfig } from './shared.mts' +import { defineConfig } from 'vitepress' + +export default defineConfig({ + ...sharedConfig, + + locales: { + root: { label: 'English', lang: 'en-US', link: '/', ...enConfig }, + fr: { label: 'Français', lang: 'fr-FR', link: '/fr/', ...frConfig }, + zh: { label: '简体中文', lang: 'zh-CN', link: '/zh/', ...zhConfig } + } +}) diff --git a/docs/.vitepress/config/shared.mts b/docs/.vitepress/config/shared.mts new file mode 100644 index 000000000..ee7850372 --- /dev/null +++ b/docs/.vitepress/config/shared.mts @@ -0,0 +1,113 @@ +import { defineConfig } from 'vitepress' + +// TODO: +// export const META_IMAGE = 'https://test-utils.vuejs.org/social.png' +export const META_IMAGE = null +export const isProduction = + process.env.NETLIFY && process.env.CONTEXT === 'production' + +if (process.env.NETLIFY) { + console.log('Netlify build', process.env.CONTEXT) +} + +const rControl = /[\u0000-\u001f]/g +const rSpecial = /[\s~`!@#$%^&*()\-_+=[\]{}|\\;:"'“”‘’<>,.?/]+/g +const rCombining = /[\u0300-\u036F]/g + +/** + * Default slugification function + */ +export const slugify = (str: string): string => + str + .normalize('NFKD') + // Remove accents + .replace(rCombining, '') + // Remove control characters + .replace(rControl, '') + // Replace special characters + .replace(rSpecial, '-') + // ensure it doesn't start with a number + .replace(/^(\d)/, '_$1') + +export const sharedConfig = defineConfig({ + title: 'Vue Test Utils', + appearance: true, + + markdown: { + theme: { + dark: 'one-dark-pro', + light: 'github-light', + }, + + anchor: { + slugify, + }, + }, + + head: [ + ['link', { rel: 'icon', type: 'image/png', href: '/logo.png' }], + + [ + 'meta', + { name: 'wwads-cn-verify', content: '7e7757b1e12abcb736ab9a754ffb617a' }, + ], + + [ + 'meta', + { + property: 'og:type', + content: 'website', + }, + ], + + [ + 'meta', + { + property: 'twitter:card', + content: 'summary_large_image', + }, + ], + // [ + // 'meta', + // { + // property: 'twitter:image', + // content: META_IMAGE, + // }, + // ], + ], + + themeConfig: { + logo: '/logo.svg', + outline: [2, 3], + + socialLinks: [ + { + icon: 'github', + link: 'https://github.com/vuejs/test-utils/', + }, + { + icon: 'discord', + link: 'https://chat.vuejs.org', + }, + ], + + footer: { + copyright: 'Copyright © 2014-present Evan You', + message: 'Released under the MIT License.', + }, + + editLink: { + pattern: 'https://github.com/vuejs/test-utils/edit/main/docs/:path', + text: 'Suggest changes', + }, + + algolia: { + appId: 'BH4D9OD16A', + apiKey: 'ee1b8516c9e5a5be9b6c25684eafc42f', + indexName: 'vue_test_utils', + searchParameters: { + facetFilters: ['tags:next'] + } + }, + }, +}) diff --git a/docs/.vitepress/config/zh.mts b/docs/.vitepress/config/zh.mts new file mode 100644 index 000000000..fd24b3a25 --- /dev/null +++ b/docs/.vitepress/config/zh.mts @@ -0,0 +1,154 @@ +import type { DefaultTheme, LocaleSpecificConfig } from 'vitepress' + +export const META_URL = '' +export const META_TITLE = 'Vue Test Utils' +export const META_DESCRIPTION = 'Vue.js 3 官方测试工具集' + +export const zhConfig: LocaleSpecificConfig = { + description: META_DESCRIPTION, + head: [ + ['meta', { property: 'og:url', content: META_URL }], + ['meta', { property: 'og:title', content: META_TITLE }], + ['meta', { property: 'og:description', content: META_DESCRIPTION }], + ['meta', { property: 'twitter:url', content: META_URL }], + ['meta', { property: 'twitter:title', content: META_TITLE }], + ['meta', { property: 'twitter:description', content: META_DESCRIPTION }] + ], + + themeConfig: { + editLink: { + pattern: 'https://github.com/vuejs/test-utils/edit/main/docs/:path', + text: '改进此页面的内容' + }, + + nav: [ + { text: '指南', link: '/zh/guide/' }, + { text: 'API 参考', link: '/zh/api/' }, + { text: '从 Vue 2 迁移', link: '/zh/migration/' }, + { + text: '更新日志', + link: 'https://github.com/vuejs/test-utils/releases' + } + ], + + sidebar: { + '/zh': [ + { + text: '安装', + link: '/zh/installation/' + }, + { + text: '基础知识', + items: [ + { + text: '开始', + link: '/zh/guide/' + }, + { + text: '快速上手', + link: '/zh/guide/essentials/a-crash-course' + }, + { + text: '条件渲染', + link: '/zh/guide/essentials/conditional-rendering' + }, + { + text: '测试事件触发', + link: '/zh/guide/essentials/event-handling' + }, + { + text: '测试表单', + link: '/zh/guide/essentials/forms' + }, + { + text: '传递数据到组件', + link: '/zh/guide/essentials/passing-data' + }, + { + text: '编写易于测试的组件', + link: '/zh/guide/essentials/easy-to-test' + } + ] + }, + { + text: '深入学习 Vue Test Utils', + items: [ + { + text: '插槽', + link: '/zh/guide/advanced/slots' + }, + { + text: '异步行为', + link: '/zh/guide/advanced/async-suspense' + }, + { + text: '发起 HTTP 请求', + link: '/zh/guide/advanced/http-requests' + }, + { + text: '过渡效果', + link: '/zh/guide/advanced/transitions' + }, + { + text: '组件实例', + link: '/zh/guide/advanced/component-instance' + }, + { + text: '复用与组合', + link: '/zh/guide/advanced/reusability-composition' + }, + { + text: '测试 v-model', + link: '/zh/guide/advanced/v-model' + }, + { + text: '测试 Vuex', + link: '/zh/guide/advanced/vuex' + }, + { + text: '测试 Vue Router', + link: '/zh/guide/advanced/vue-router' + }, + { + text: '测试 Teleport', + link: '/zh/guide/advanced/teleport' + }, + { + text: '测试替身 (stub) 和浅挂载', + link: '/zh/guide/advanced/stubs-shallow-mount' + }, + { + text: '测试服务端渲染', + link: '/zh/guide/advanced/ssr' + } + ] + }, + { + text: '扩展 Vue Test Utils', + items: [ + { + text: '插件', + link: '/zh/guide/extending-vtu/plugins' + }, + { + text: '社区与学习资源', + link: '/zh/guide/extending-vtu/community-learning' + } + ] + }, + { + text: '常见问题', + link: '/zh/guide/faq/' + }, + { + text: '从 Vue 2 迁移', + link: '/zh/migration/' + }, + { + text: 'API 参考', + link: '/zh/api/' + } + ] + } + } +} diff --git a/docs/.vitepress/theme/custom.css b/docs/.vitepress/theme/custom.css new file mode 100644 index 000000000..d59dd22e2 --- /dev/null +++ b/docs/.vitepress/theme/custom.css @@ -0,0 +1,8 @@ +.VPContent { + display: flex; + align-items: center; +} + +.VPHome { + flex-grow: 1; +} \ No newline at end of file diff --git a/docs/.vitepress/theme/index.mts b/docs/.vitepress/theme/index.mts new file mode 100644 index 000000000..716b55a15 --- /dev/null +++ b/docs/.vitepress/theme/index.mts @@ -0,0 +1,19 @@ +import { h } from 'vue' +import Theme from 'vitepress/theme' +import TranslationStatus from 'vitepress-translation-helper/ui/TranslationStatus.vue' +import status from '../translation-status.json' +import './custom.css' +const i18nLabels = { + fr: 'La traduction est synchronisée avec les docs du ${date} dont le hash du commit est ${hash}.', + zh: '该翻译已同步到了 ${date} 的版本,其对应的 commit hash 是 ${hash}。' +} + + +export default { + ...Theme, + Layout() { + return h(Theme.Layout, null, { + 'doc-before': () => h(TranslationStatus, { status, i18nLabels }), + }) + }, +} diff --git a/docs/.vitepress/translation-status.json b/docs/.vitepress/translation-status.json new file mode 100644 index 000000000..b7a6d4c97 --- /dev/null +++ b/docs/.vitepress/translation-status.json @@ -0,0 +1,10 @@ +{ + "fr": { + "hash": "644917a", + "date": "2024-05-28" + }, + "zh": { + "hash": "7c55128", + "date": "2024-11-28" + } +} \ No newline at end of file diff --git a/docs/.vitepress/tsconfig.vitepress.json b/docs/.vitepress/tsconfig.vitepress.json new file mode 100644 index 000000000..1a11e5d76 --- /dev/null +++ b/docs/.vitepress/tsconfig.vitepress.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "skipLibCheck": true, + "noEmit": true, + "allowImportingTsExtensions": true, + "resolveJsonModule": true + }, + "include": ["./config", "./theme"] +} diff --git a/docs/api/index.md b/docs/api/index.md index 1e63d406b..7e7818207 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -14,7 +14,7 @@ Note that when mocking dates/timers with Vitest, this must be called after ```ts interface MountingOptions { - attachTo?: HTMLElement | string + attachTo?: Element | string attrs?: Record data?: () => {} extends Data ? any : Data extends object ? Partial : any props?: (RawProps & Props) | ({} extends Props ? null : never) @@ -46,7 +46,7 @@ test('mounts a component', () => { Notice that `mount` accepts a second parameter to define the component's state configuration. -**Exemple : mounting with component props and a Vue App plugin** +**Example : mounting with component props and a Vue App plugin** ```js const wrapper = mount(Component, { @@ -74,13 +74,15 @@ Specify the node to mount the component on. This is not available when using `re **Signature:** ```ts -attachTo?: HTMLElement | string +attachTo?: Element | string ``` **Details:** Can be a valid CSS selector, or an [`Element`](https://developer.mozilla.org/en-US/docs/Web/API/Element) connected to the document. +Note that the component is appended to the node, it doesn't replace the whole content of the node. If you mount the component on the same node in multiple tests - make sure to unmount it after each test by calling `wrapper.unmount()`, this will remove the rendered elements from the node. + `Component.vue`: ```vue @@ -827,9 +829,9 @@ test('shallow', () => { const wrapper = mount(Component, { shallow: true }) expect(wrapper.html()).toEqual( - `` + `` ) -} +}) ``` ::: tip @@ -1026,6 +1028,11 @@ find(selector: string | RefSelector): DOMWrapper; You can use the same syntax `querySelector` implements. `find` is basically an alias for `querySelector`. In addition you can search for element refs. +It is similar to `get`, but `find` returns an ErrorWrapper if an element is not found while [`get`](#get) will throw an error. + +As a rule of thumb, always use `find` when you are asserting something doesn't exist. If you are asserting something does exist, use [`get`](#get). + + `Component.vue`: ```vue @@ -1099,8 +1106,8 @@ Finds a Vue Component instance and returns a `VueWrapper` if found. Returns `Err ```ts findComponent(selector: string): WrapperLike -findComponent(selector: T | Exclude): VueWrapper> -findComponent(selector: T | string): DOMWrapper +findComponent(selector: T | Exclude>): VueWrapper> +findComponent>(selector: T | string): DOMWrapper findComponent(selector: NameSelector | RefSelector): VueWrapper findComponent(selector: T | FindComponentSelector): VueWrapper findComponent(selector: FindComponentSelector): WrapperLike @@ -1172,7 +1179,7 @@ test('findComponent', () => { ``` :::warning -If `ref` in component points to HTML element, `findComponent` will return empty wrapper. This is intended behaviour +If `ref` in component points to HTML element, `findComponent` will return empty wrapper. This is intended behaviour. ::: :::warning Usage with CSS selectors @@ -1217,9 +1224,9 @@ wrapper.findComponent('.foo') // returns VueWrapper ```ts findAllComponents(selector: string): WrapperLike[] -findAllComponents(selector: T | Exclude): VueWrapper>[] -findAllComponents(selector: string): DOMWrapper[] -findAllComponents(selector: T): DOMWrapper[] +findAllComponents(selector: T | Exclude>): VueWrapper>[] +findAllComponents>(selector: string): DOMWrapper[] +findAllComponents>(selector: T): DOMWrapper[] findAllComponents(selector: NameSelector): VueWrapper[] findAllComponents(selector: T | FindAllComponentsSelector): VueWrapper[] findAllComponents(selector: FindAllComponentsSelector): WrapperLike[] @@ -1276,9 +1283,9 @@ get(selector: string): Omit, 'exists'> **Details:** -It is similar to `find`, but `get` throws instead of returning a ErrorWrapper. +It is similar to `find`, but `get` throws an error if an element is not found while [`find`](#find) will return an ErrorWrapper. -As a rule of thumb, always use get except when you are asserting something doesn't exist. In that case use [`find`](#find). +As a rule of thumb, always use `get` except when you are asserting something doesn't exist. In that case use [`find`](#find). `Component.vue`: @@ -1317,7 +1324,7 @@ getComponent(selector: any): Omit` } test('isVisible', () => { - const wrapper = mount(Component) + const wrapper = mount(Component, { + attachTo: document.body + }); - expect(wrapper.find('span').isVisible()).toBe(false) + expect(wrapper.find('span').isVisible()).toBe(false); }) ``` @@ -1678,20 +1691,20 @@ test('setValue on checkbox', async () => { const wrapper = mount(Component) await wrapper.find('input[type="checkbox"]').setValue(true) - expect(wrapper.find('div')).toBe(true) + expect(wrapper.find('div').exists()).toBe(true) await wrapper.find('input[type="checkbox"]').setValue(false) - expect(wrapper.find('div')).toBe(false) + expect(wrapper.find('div').exists()).toBe(false) }) -test('setValue on input text', () => { +test('setValue on input text', async () => { const wrapper = mount(Component) await wrapper.find('input[type="text"]').setValue('hello!') expect(wrapper.find('p').text()).toBe('Text: hello!') }) -test('setValue on multi select', () => { +test('setValue on multi select', async () => { const wrapper = mount(Component) // For select without multiple @@ -1876,7 +1889,7 @@ Creates a Wrapper that contains the mounted and rendered Vue component to test w ```ts interface MountingOptions { - attachTo?: HTMLElement | string + attachTo?: Element | string attrs?: Record data?: () => {} extends Data ? any : Data extends object ? Partial : any props?: (RawProps & Props) | ({} extends Props ? null : never) @@ -1951,7 +1964,7 @@ type GlobalMountOptions = { Instead of configuring mounting options on a per test basis, you can configure them for your entire test suite. These will be used by default every time you `mount` a component. If desired, you can then override your defaults on a per test basis. -**Exemple :** +**Example :** An example might be globally mocking the `$t` variable from vue-i18n and a component: diff --git a/docs/fr/.vitepress/locale-config.ts b/docs/fr/.vitepress/locale-config.ts deleted file mode 100644 index 55ccb2719..000000000 --- a/docs/fr/.vitepress/locale-config.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { DefaultTheme } from "vitepress"; - -const frLocaleConfig: DefaultTheme.LocaleConfig & Omit = { - label: 'Français', - selectText: 'Langues', - nav: [ - { text: 'Guide', link: '/fr/guide/' }, - { text: 'API', link: '/fr/api/' }, - { - text: 'FAQ', - link: '/fr/guide/faq/' - }, - { text: 'Migrer depuis Vue 2', link: '/fr/migration/' }, - { - text: 'Journal de modifications', - link: 'https://github.com/vuejs/test-utils/releases' - } - ], - sidebar: [ - { - text: 'Installation', - link: '/fr/installation/' - }, - { - text: 'Les Bases', - collapsable: false, - children: [ - { text: 'Pour commencer', link: '/fr/guide/' }, - { text: 'Cours rapide', link: '/fr/guide/essentials/a-crash-course' }, - { - text: 'Rendu conditionnel', - link: '/fr/guide/essentials/conditional-rendering' - }, - { - text: 'Tester les évènements émis', - link: '/fr/guide/essentials/event-handling' - }, - { text: 'Tester les formulaires', link: '/fr/guide/essentials/forms' }, - { - text: 'Passer des données aux Composants', - link: '/fr/guide/essentials/passing-data' - }, - { - text: 'Écrire des composants facile à tester', - link: '/fr/guide/essentials/easy-to-test' - } - ] - }, - { - text: 'Vue Test Utils en détail', - collapsable: false, - children: [ - { text: 'Slots', link: '/fr/guide/advanced/slots' }, - { - text: 'Comportement asynchrone', - link: '/fr/guide/advanced/async-suspense' - }, - { - text: 'Faire des requêtes HTTP', - link: '/fr/guide/advanced/http-requests' - }, - { text: 'Transitions', link: '/fr/guide/advanced/transitions' }, - { - text: 'Instance de Composant', - link: '/fr/guide/advanced/component-instance' - }, - { - text: 'Réutilisabilité et Composition', - link: '/fr/guide/advanced/reusability-composition' - }, - { text: 'Tester v-model', link: '/fr/guide/advanced/v-model' }, - { text: 'Tester Vuex', link: '/fr/guide/advanced/vuex' }, - { text: 'Tester Vue Router', link: '/fr/guide/advanced/vue-router' }, - { text: 'Tester Teleport', link: '/fr/guide/advanced/teleport' }, - { - text: 'Composants de Substitution (Stubs) et Montage Partiel', - link: '/fr/guide/advanced/stubs-shallow-mount' - }, - { text: 'Tester le Rendu côté Serveur (SSR)', link: '/fr/guide/advanced/ssr' } - ] - }, - { - text: 'Extensions de Vue Test Utils', - collapsable: false, - children: [ - { text: 'Plugins', link: '/fr/guide/extending-vtu/plugins' }, - { - text: 'Communauté et Apprentissage', - link: '/fr/guide/extending-vtu/community-learning' - } - ] - }, - { - text: 'FAQ', - link: '/fr/guide/faq/' - }, - { - text: 'Migrer depuis Vue 2', - link: '/fr/migration/' - }, - { - text: 'API', - link: '/fr/api/' - } - ] -}; - -export { frLocaleConfig }; diff --git a/docs/fr/api/index.md b/docs/fr/api/index.md index eafb8e41e..f58b3d926 100644 --- a/docs/fr/api/index.md +++ b/docs/fr/api/index.md @@ -12,7 +12,7 @@ Crée un `Wrapper` qui contient le composant Vue monté et rendu pour le test. ```ts interface MountingOptions { - attachTo?: HTMLElement | string + attachTo?: Element | string attrs?: Record data?: () => {} extends Data ? any : Data extends object ? Partial : any props?: (RawProps & Props) | ({} extends Props ? null : never) @@ -72,7 +72,7 @@ Spécifie le nœud où monter le composant. **Signature :** ```ts -attachTo?: HTMLElement | string +attachTo?: Element | string ``` **Utilisation :** @@ -825,7 +825,7 @@ test('shallow', () => { const wrapper = mount(Component, { shallow: true }); expect(wrapper.html()).toEqual( - ``, + ``, ); }); ``` @@ -1024,6 +1024,10 @@ find(selector: string | RefSelector): DOMWrapper; Vous pouvez utiliser la même syntaxe qu'implémente `querySelector`. `find` est en quelque sorte un alias pour `querySelector`. En plus, vous pouvez rechercher des références d'éléments. +Il est similaire à `get`, mais `find` retourne un `ErrorWrapper` si un élément n'est pas trouvé tandis que [`get`](#get) lancera une erreur. + +En règle générale, utilisez toujours `find` lorsque vous souhaitez vérifier que quelque chose n'existe pas. Si vous savez que quelque chose existe, utilisez [`get`](#get). + `Component.vue`: ```vue @@ -1097,8 +1101,8 @@ Trouve une instance de composant Vue et renvoie un `VueWrapper` si trouvé. Renv ```ts findComponent(selector: string): WrapperLike -findComponent(selector: T | Exclude): VueWrapper> -findComponent(selector: T | string): DOMWrapper +findComponent(selector: T | Exclude>): VueWrapper> +findComponent>(selector: T | string): DOMWrapper findComponent(selector: NameSelector | RefSelector): VueWrapper findComponent(selector: T | FindComponentSelector): VueWrapper findComponent(selector: FindComponentSelector): WrapperLike @@ -1214,9 +1218,9 @@ wrapper.findComponent('.foo'); // retourne VueWrapper ```ts findAllComponents(selector: string): WrapperLike[] -findAllComponents(selector: T | Exclude): VueWrapper>[] -findAllComponents(selector: string): DOMWrapper[] -findAllComponents(selector: T): DOMWrapper[] +findAllComponents(selector: T | Exclude>): VueWrapper>[] +findAllComponents>(selector: string): DOMWrapper[] +findAllComponents>(selector: T): DOMWrapper[] findAllComponents(selector: NameSelector): VueWrapper[] findAllComponents(selector: T | FindAllComponentsSelector): VueWrapper[] findAllComponents(selector: FindAllComponentsSelector): WrapperLike[] @@ -1273,9 +1277,10 @@ get(selector: string): Omit, 'exists'> **Utilisation :** -Similaire à `find`, mais `get` retourne une exception au lieu de renvoyer un `ErrorWrapper`. +It is similar to `find`, but `get` throws an error if an element is not found while [`find`](#find) will return an ErrorWrapper. +Similaire à `find`, mais `get` renvoie une erreur si un élément n'est pas trouvé tandis que [`find`](#find) renverra un `ErrorWrapper`. -En règle générale, utilisez toujours `get` sauf lorsque vous vérifiez que quelque chose n'existe pas. Dans ce cas, utilisez `find`. +En règle générale, utilisez toujours `get` sauf lorsque vous voulez vérifier qu'un élément n'existe pas. Dans ce cas, utilisez [`find`](#find). `Component.vue`: @@ -1314,7 +1319,7 @@ getComponent(selector: any): Omit`, }; test('isVisible', () => { - const wrapper = mount(Component); + const wrapper = mount(Component, { + attachTo: document.body + }); expect(wrapper.find('span').isVisible()).toBe(false); }); @@ -1672,10 +1683,10 @@ test('setValue sur une checkbox', async () => { const wrapper = mount(Component); await wrapper.find('input[type="checkbox"]').setValue(true); - expect(wrapper.find('div')).toBe(true); + expect(wrapper.find('div').exists()).toBe(true); await wrapper.find('input[type="checkbox"]').setValue(false); - expect(wrapper.find('div')).toBe(false); + expect(wrapper.find('div').exists()).toBe(false); }); test('setValue sur un champ texte', async () => { @@ -1870,7 +1881,7 @@ Crée un `Wrapper` qui contient le composant Vue monté et rendu pour le tester ```ts interface MountingOptions { - attachTo?: HTMLElement | string + attachTo?: Element | string attrs?: Record data?: () => {} extends Data ? any : Data extends object ? Partial : any props?: (RawProps & Props) | ({} extends Props ? null : never) diff --git a/docs/fr/guide/advanced/teleport.md b/docs/fr/guide/advanced/teleport.md index 2cc205fc8..12cb4fa2e 100644 --- a/docs/fr/guide/advanced/teleport.md +++ b/docs/fr/guide/advanced/teleport.md @@ -101,7 +101,7 @@ beforeEach(() => { afterEach(() => { // nous nettoyons un peu - document.body.outerHTML = ''; + document.body.innerHTML = ''; }); test('teleport', async () => { @@ -174,7 +174,7 @@ beforeEach(() => { afterEach(() => { // nous nettoyons un peu - document.body.outerHTML = ''; + document.body.innerHTML = ''; }); test('teleport', async () => { @@ -188,6 +188,22 @@ test('teleport', async () => { }); ``` +Vous pouvez remplacer teleport par un stub en utilisant `teleport: true`: +```ts +import { mount } from '@vue/test-utils' +import Navbar from './Navbar.vue' + +test('teleport', async () => { + const wrapper = mount(Navbar, { + global: { + stubs: { + teleport: true + } + } + }) +}) +``` + ## Conclusion - Créez une cible de téléportation avec `document.createElement`. diff --git a/docs/fr/guide/advanced/vue-router.md b/docs/fr/guide/advanced/vue-router.md index 13f67bcbd..479632b87 100644 --- a/docs/fr/guide/advanced/vue-router.md +++ b/docs/fr/guide/advanced/vue-router.md @@ -187,7 +187,7 @@ console.warn node_modules/@vue/runtime-core/dist/runtime-core.cjs.js:39 Les composants `` et `` ne sont pas trouvés. Nous devons installer Vue Router ! Comme Vue Router est un plugin, nous l'installons en utilisant l'option de `mount` : `global.plugins` : -```js {10,11,12} +```js {12,13,14} import { mount } from '@vue/test-utils'; import { createRouter, createWebHistory } from 'vue-router'; import { routes } from "@/router"; // Cet import devrait pointer vers votre fichier de configuration des routes. @@ -218,7 +218,7 @@ Le `warning` n'est pas très explicite. En fait, cela est lié au fait que **Vue Vue Router fournit une fonction `isReady` qui nous informe lorsque le routeur est prêt. Nous pouvons alors l'`await` pour nous assurer que la navigation initiale a eu lieu. -```js {11,12} +```js {13,14} import { mount } from '@vue/test-utils'; import { createRouter, createWebHistory } from 'vue-router'; import { routes } from "@/router"; @@ -247,7 +247,7 @@ Le test passe enfin ! Cela a été assez laborieux, mais désormais nous no Maintenant, allons sur `/posts` et assurons-nous que le routage fonctionne comme prévu : -```js {19,20} +```js {21,22} import { mount } from '@vue/test-utils'; import { createRouter, createWebHistory } from 'vue-router'; import { routes } from "@/router"; @@ -288,7 +288,7 @@ Une fois de plus, en raison de la nature asynchrone de Vue Router 4, nous devons Cependant, il n'y a pas de `hook` `hasNavigated` sur lequel nous pouvons `await`. Une alternative est d'utiliser la fonction `flushPromises` exportée de Vue Test Utils : -```js {1,20} +```js {1,22} import { mount, flushPromises } from '@vue/test-utils'; import { createRouter, createWebHistory } from 'vue-router'; import { routes } from "@/router"; @@ -317,7 +317,7 @@ test('routing', async () => { Cela passe. Super ! Cependant, c'est très laborieux - et cela concerne une petite application triviale. C'est pour cette raison que l'utilisation d'un routeur simulé est une approche courante lors des tests de composants Vue avec Vue Test Utils. Si vous préférez continuer à utiliser un routeur réel, gardez à l'esprit que chaque test doit utiliser son propre instance du routeur de cette manière : -```js {1,20} +```js {1,22} import { mount, flushPromises } from '@vue/test-utils'; import { createRouter, createWebHistory } from 'vue-router'; import { routes } from "@/router"; diff --git a/docs/fr/guide/essentials/a-crash-course.md b/docs/fr/guide/essentials/a-crash-course.md index eca8f208a..57e7684e4 100644 --- a/docs/fr/guide/essentials/a-crash-course.md +++ b/docs/fr/guide/essentials/a-crash-course.md @@ -16,22 +16,16 @@ Commençons par un simple composant TodoApp avec une seule tâche :
- ``` @@ -116,33 +110,25 @@ Si nous exécutons ce test, il échouera. Modifions `TodoApp.vue` pour avoir les - ``` diff --git a/docs/fr/guide/essentials/conditional-rendering.md b/docs/fr/guide/essentials/conditional-rendering.md index 761764820..5b7411c77 100644 --- a/docs/fr/guide/essentials/conditional-rendering.md +++ b/docs/fr/guide/essentials/conditional-rendering.md @@ -8,20 +8,20 @@ Cet article est également disponible sous la forme d'une [courte vidéo](https: L'une des fonctionnalités les plus basiques de Vue est la capacité d'insérer et de supprimer dynamiquement des éléments avec `v-if`. Voyons comment tester un composant qui utilise `v-if`. -```js -const Nav = { - template: ` - - `, - data() { - return { - admin: false, - }; - }, -}; +```vue + + + + ``` Dans le composant `