From c5f27bc52d90979950249dc83d851c8c6d36a501 Mon Sep 17 00:00:00 2001 From: meatjam <851404658@qq.com> Date: Thu, 15 Feb 2024 20:44:57 +0800 Subject: [PATCH 1/6] 11 --- playground | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playground b/playground index 0dcb457f9..640bb3cba 160000 --- a/playground +++ b/playground @@ -1 +1 @@ -Subproject commit 0dcb457f970b437c30b2d5286b5abcde0e59b691 +Subproject commit 640bb3cba0cc44ae7a56c5c7f64afebb963e972e From 5c5237a29219e7e5a2d58db4db64c86d43bda457 Mon Sep 17 00:00:00 2001 From: meatjam <851404658@qq.com> Date: Thu, 15 Feb 2024 20:45:07 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E7=AE=80=E5=8C=96=E6=A8=A1=E6=9D=BF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- template/base/.vscode/extensions.json | 3 - template/base/src/assets/base.css | 86 ------------------ template/base/src/assets/main.css | 39 ++------ template/code/default/src/App.vue | 48 +--------- .../default/src/components/HelloWorld.vue | 44 ---------- .../default/src/components/TheWelcome.vue | 88 ------------------- .../default/src/components/WelcomeItem.vue | 87 ------------------ .../src/components/icons/IconCommunity.vue | 7 -- .../components/icons/IconDocumentation.vue | 7 -- .../src/components/icons/IconEcosystem.vue | 7 -- .../src/components/icons/IconSupport.vue | 7 -- .../src/components/icons/IconTooling.vue | 19 ---- template/code/router/src/App.vue | 82 +---------------- .../code/router/src/components/HelloWorld.vue | 44 ---------- .../code/router/src/components/TheWelcome.vue | 88 ------------------- .../router/src/components/WelcomeItem.vue | 86 ------------------ .../src/components/icons/IconCommunity.vue | 7 -- .../components/icons/IconDocumentation.vue | 7 -- .../src/components/icons/IconEcosystem.vue | 7 -- .../src/components/icons/IconSupport.vue | 7 -- .../src/components/icons/IconTooling.vue | 19 ---- template/code/router/src/router/index.js | 11 +-- template/code/router/src/views/AboutView.vue | 15 ---- template/code/router/src/views/Home.vue | 5 ++ template/code/router/src/views/HomeView.vue | 9 -- template/code/typescript-default/src/App.vue | 48 +--------- .../src/components/HelloWorld.vue | 41 --------- .../src/components/TheWelcome.vue | 88 ------------------- .../src/components/WelcomeItem.vue | 87 ------------------ .../src/components/icons/IconCommunity.vue | 7 -- .../components/icons/IconDocumentation.vue | 7 -- .../src/components/icons/IconEcosystem.vue | 7 -- .../src/components/icons/IconSupport.vue | 7 -- .../src/components/icons/IconTooling.vue | 19 ---- utils/renderEslint.ts | 4 +- 35 files changed, 22 insertions(+), 1122 deletions(-) delete mode 100644 template/base/.vscode/extensions.json delete mode 100644 template/base/src/assets/base.css delete mode 100644 template/code/default/src/components/HelloWorld.vue delete mode 100644 template/code/default/src/components/TheWelcome.vue delete mode 100644 template/code/default/src/components/WelcomeItem.vue delete mode 100644 template/code/default/src/components/icons/IconCommunity.vue delete mode 100644 template/code/default/src/components/icons/IconDocumentation.vue delete mode 100644 template/code/default/src/components/icons/IconEcosystem.vue delete mode 100644 template/code/default/src/components/icons/IconSupport.vue delete mode 100644 template/code/default/src/components/icons/IconTooling.vue delete mode 100644 template/code/router/src/components/HelloWorld.vue delete mode 100644 template/code/router/src/components/TheWelcome.vue delete mode 100644 template/code/router/src/components/WelcomeItem.vue delete mode 100644 template/code/router/src/components/icons/IconCommunity.vue delete mode 100644 template/code/router/src/components/icons/IconDocumentation.vue delete mode 100644 template/code/router/src/components/icons/IconEcosystem.vue delete mode 100644 template/code/router/src/components/icons/IconSupport.vue delete mode 100644 template/code/router/src/components/icons/IconTooling.vue delete mode 100644 template/code/router/src/views/AboutView.vue create mode 100644 template/code/router/src/views/Home.vue delete mode 100644 template/code/router/src/views/HomeView.vue delete mode 100644 template/code/typescript-default/src/components/HelloWorld.vue delete mode 100644 template/code/typescript-default/src/components/TheWelcome.vue delete mode 100644 template/code/typescript-default/src/components/WelcomeItem.vue delete mode 100644 template/code/typescript-default/src/components/icons/IconCommunity.vue delete mode 100644 template/code/typescript-default/src/components/icons/IconDocumentation.vue delete mode 100644 template/code/typescript-default/src/components/icons/IconEcosystem.vue delete mode 100644 template/code/typescript-default/src/components/icons/IconSupport.vue delete mode 100644 template/code/typescript-default/src/components/icons/IconTooling.vue diff --git a/template/base/.vscode/extensions.json b/template/base/.vscode/extensions.json deleted file mode 100644 index c0a6e5a48..000000000 --- a/template/base/.vscode/extensions.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] -} diff --git a/template/base/src/assets/base.css b/template/base/src/assets/base.css deleted file mode 100644 index 8816868a4..000000000 --- a/template/base/src/assets/base.css +++ /dev/null @@ -1,86 +0,0 @@ -/* color palette from */ -:root { - --vt-c-white: #ffffff; - --vt-c-white-soft: #f8f8f8; - --vt-c-white-mute: #f2f2f2; - - --vt-c-black: #181818; - --vt-c-black-soft: #222222; - --vt-c-black-mute: #282828; - - --vt-c-indigo: #2c3e50; - - --vt-c-divider-light-1: rgba(60, 60, 60, 0.29); - --vt-c-divider-light-2: rgba(60, 60, 60, 0.12); - --vt-c-divider-dark-1: rgba(84, 84, 84, 0.65); - --vt-c-divider-dark-2: rgba(84, 84, 84, 0.48); - - --vt-c-text-light-1: var(--vt-c-indigo); - --vt-c-text-light-2: rgba(60, 60, 60, 0.66); - --vt-c-text-dark-1: var(--vt-c-white); - --vt-c-text-dark-2: rgba(235, 235, 235, 0.64); -} - -/* semantic color variables for this project */ -:root { - --color-background: var(--vt-c-white); - --color-background-soft: var(--vt-c-white-soft); - --color-background-mute: var(--vt-c-white-mute); - - --color-border: var(--vt-c-divider-light-2); - --color-border-hover: var(--vt-c-divider-light-1); - - --color-heading: var(--vt-c-text-light-1); - --color-text: var(--vt-c-text-light-1); - - --section-gap: 160px; -} - -@media (prefers-color-scheme: dark) { - :root { - --color-background: var(--vt-c-black); - --color-background-soft: var(--vt-c-black-soft); - --color-background-mute: var(--vt-c-black-mute); - - --color-border: var(--vt-c-divider-dark-2); - --color-border-hover: var(--vt-c-divider-dark-1); - - --color-heading: var(--vt-c-text-dark-1); - --color-text: var(--vt-c-text-dark-2); - } -} - -*, -*::before, -*::after { - box-sizing: border-box; - margin: 0; - font-weight: normal; -} - -body { - min-height: 100vh; - color: var(--color-text); - background: var(--color-background); - transition: - color 0.5s, - background-color 0.5s; - line-height: 1.6; - font-family: - Inter, - -apple-system, - BlinkMacSystemFont, - 'Segoe UI', - Roboto, - Oxygen, - Ubuntu, - Cantarell, - 'Fira Sans', - 'Droid Sans', - 'Helvetica Neue', - sans-serif; - font-size: 15px; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} diff --git a/template/base/src/assets/main.css b/template/base/src/assets/main.css index 36fb845b5..5aadc6ceb 100644 --- a/template/base/src/assets/main.css +++ b/template/base/src/assets/main.css @@ -1,35 +1,6 @@ -@import './base.css'; - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - font-weight: normal; -} - -a, -.green { - text-decoration: none; - color: hsla(160, 100%, 37%, 1); - transition: 0.4s; - padding: 3px; -} - -@media (hover: hover) { - a:hover { - background-color: hsla(160, 100%, 37%, 0.2); - } -} - -@media (min-width: 1024px) { - body { - display: flex; - place-items: center; - } - - #app { - display: grid; - grid-template-columns: 1fr 1fr; - padding: 0 2rem; - } +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; } diff --git a/template/code/default/src/App.vue b/template/code/default/src/App.vue index 633a5dfe4..05664635c 100644 --- a/template/code/default/src/App.vue +++ b/template/code/default/src/App.vue @@ -1,47 +1,5 @@ - + - - - + diff --git a/template/code/default/src/components/HelloWorld.vue b/template/code/default/src/components/HelloWorld.vue deleted file mode 100644 index 5fb372c9c..000000000 --- a/template/code/default/src/components/HelloWorld.vue +++ /dev/null @@ -1,44 +0,0 @@ - - - - - diff --git a/template/code/default/src/components/TheWelcome.vue b/template/code/default/src/components/TheWelcome.vue deleted file mode 100644 index dab95367d..000000000 --- a/template/code/default/src/components/TheWelcome.vue +++ /dev/null @@ -1,88 +0,0 @@ - - - diff --git a/template/code/default/src/components/WelcomeItem.vue b/template/code/default/src/components/WelcomeItem.vue deleted file mode 100644 index 6d7086aea..000000000 --- a/template/code/default/src/components/WelcomeItem.vue +++ /dev/null @@ -1,87 +0,0 @@ - - - diff --git a/template/code/default/src/components/icons/IconCommunity.vue b/template/code/default/src/components/icons/IconCommunity.vue deleted file mode 100644 index 2dc8b0552..000000000 --- a/template/code/default/src/components/icons/IconCommunity.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/template/code/default/src/components/icons/IconDocumentation.vue b/template/code/default/src/components/icons/IconDocumentation.vue deleted file mode 100644 index 6d4791cfb..000000000 --- a/template/code/default/src/components/icons/IconDocumentation.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/template/code/default/src/components/icons/IconEcosystem.vue b/template/code/default/src/components/icons/IconEcosystem.vue deleted file mode 100644 index c3a4f078c..000000000 --- a/template/code/default/src/components/icons/IconEcosystem.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/template/code/default/src/components/icons/IconSupport.vue b/template/code/default/src/components/icons/IconSupport.vue deleted file mode 100644 index 7452834d3..000000000 --- a/template/code/default/src/components/icons/IconSupport.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/template/code/default/src/components/icons/IconTooling.vue b/template/code/default/src/components/icons/IconTooling.vue deleted file mode 100644 index 660598d7c..000000000 --- a/template/code/default/src/components/icons/IconTooling.vue +++ /dev/null @@ -1,19 +0,0 @@ - - diff --git a/template/code/router/src/App.vue b/template/code/router/src/App.vue index e86419500..170f14a24 100644 --- a/template/code/router/src/App.vue +++ b/template/code/router/src/App.vue @@ -1,85 +1,9 @@ - - + diff --git a/template/code/router/src/components/HelloWorld.vue b/template/code/router/src/components/HelloWorld.vue deleted file mode 100644 index 5fb372c9c..000000000 --- a/template/code/router/src/components/HelloWorld.vue +++ /dev/null @@ -1,44 +0,0 @@ - - - - - diff --git a/template/code/router/src/components/TheWelcome.vue b/template/code/router/src/components/TheWelcome.vue deleted file mode 100644 index dab95367d..000000000 --- a/template/code/router/src/components/TheWelcome.vue +++ /dev/null @@ -1,88 +0,0 @@ - - - diff --git a/template/code/router/src/components/WelcomeItem.vue b/template/code/router/src/components/WelcomeItem.vue deleted file mode 100644 index ac366d074..000000000 --- a/template/code/router/src/components/WelcomeItem.vue +++ /dev/null @@ -1,86 +0,0 @@ - - - diff --git a/template/code/router/src/components/icons/IconCommunity.vue b/template/code/router/src/components/icons/IconCommunity.vue deleted file mode 100644 index 2dc8b0552..000000000 --- a/template/code/router/src/components/icons/IconCommunity.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/template/code/router/src/components/icons/IconDocumentation.vue b/template/code/router/src/components/icons/IconDocumentation.vue deleted file mode 100644 index 6d4791cfb..000000000 --- a/template/code/router/src/components/icons/IconDocumentation.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/template/code/router/src/components/icons/IconEcosystem.vue b/template/code/router/src/components/icons/IconEcosystem.vue deleted file mode 100644 index c3a4f078c..000000000 --- a/template/code/router/src/components/icons/IconEcosystem.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/template/code/router/src/components/icons/IconSupport.vue b/template/code/router/src/components/icons/IconSupport.vue deleted file mode 100644 index 7452834d3..000000000 --- a/template/code/router/src/components/icons/IconSupport.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/template/code/router/src/components/icons/IconTooling.vue b/template/code/router/src/components/icons/IconTooling.vue deleted file mode 100644 index 660598d7c..000000000 --- a/template/code/router/src/components/icons/IconTooling.vue +++ /dev/null @@ -1,19 +0,0 @@ - - diff --git a/template/code/router/src/router/index.js b/template/code/router/src/router/index.js index a49ae507f..ff991f568 100644 --- a/template/code/router/src/router/index.js +++ b/template/code/router/src/router/index.js @@ -1,5 +1,4 @@ import { createRouter, createWebHistory } from 'vue-router' -import HomeView from '../views/HomeView.vue' const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), @@ -7,15 +6,7 @@ const router = createRouter({ { path: '/', name: 'home', - component: HomeView - }, - { - path: '/about', - name: 'about', - // route level code-splitting - // this generates a separate chunk (About.[hash].js) for this route - // which is lazy-loaded when the route is visited. - component: () => import('../views/AboutView.vue') + component: () => import('../views/Home.vue') } ] }) diff --git a/template/code/router/src/views/AboutView.vue b/template/code/router/src/views/AboutView.vue deleted file mode 100644 index 756ad2a17..000000000 --- a/template/code/router/src/views/AboutView.vue +++ /dev/null @@ -1,15 +0,0 @@ - - - diff --git a/template/code/router/src/views/Home.vue b/template/code/router/src/views/Home.vue new file mode 100644 index 000000000..c6aadabc2 --- /dev/null +++ b/template/code/router/src/views/Home.vue @@ -0,0 +1,5 @@ + + + + + diff --git a/template/code/router/src/views/HomeView.vue b/template/code/router/src/views/HomeView.vue deleted file mode 100644 index 6bb706f08..000000000 --- a/template/code/router/src/views/HomeView.vue +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/template/code/typescript-default/src/App.vue b/template/code/typescript-default/src/App.vue index d05208d6a..681c84993 100644 --- a/template/code/typescript-default/src/App.vue +++ b/template/code/typescript-default/src/App.vue @@ -1,47 +1,5 @@ - + - - - + diff --git a/template/code/typescript-default/src/components/HelloWorld.vue b/template/code/typescript-default/src/components/HelloWorld.vue deleted file mode 100644 index e1a721cc1..000000000 --- a/template/code/typescript-default/src/components/HelloWorld.vue +++ /dev/null @@ -1,41 +0,0 @@ - - - - - diff --git a/template/code/typescript-default/src/components/TheWelcome.vue b/template/code/typescript-default/src/components/TheWelcome.vue deleted file mode 100644 index 49d8f7354..000000000 --- a/template/code/typescript-default/src/components/TheWelcome.vue +++ /dev/null @@ -1,88 +0,0 @@ - - - diff --git a/template/code/typescript-default/src/components/WelcomeItem.vue b/template/code/typescript-default/src/components/WelcomeItem.vue deleted file mode 100644 index 6d7086aea..000000000 --- a/template/code/typescript-default/src/components/WelcomeItem.vue +++ /dev/null @@ -1,87 +0,0 @@ - - - diff --git a/template/code/typescript-default/src/components/icons/IconCommunity.vue b/template/code/typescript-default/src/components/icons/IconCommunity.vue deleted file mode 100644 index 2dc8b0552..000000000 --- a/template/code/typescript-default/src/components/icons/IconCommunity.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/template/code/typescript-default/src/components/icons/IconDocumentation.vue b/template/code/typescript-default/src/components/icons/IconDocumentation.vue deleted file mode 100644 index 6d4791cfb..000000000 --- a/template/code/typescript-default/src/components/icons/IconDocumentation.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/template/code/typescript-default/src/components/icons/IconEcosystem.vue b/template/code/typescript-default/src/components/icons/IconEcosystem.vue deleted file mode 100644 index c3a4f078c..000000000 --- a/template/code/typescript-default/src/components/icons/IconEcosystem.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/template/code/typescript-default/src/components/icons/IconSupport.vue b/template/code/typescript-default/src/components/icons/IconSupport.vue deleted file mode 100644 index 7452834d3..000000000 --- a/template/code/typescript-default/src/components/icons/IconSupport.vue +++ /dev/null @@ -1,7 +0,0 @@ - diff --git a/template/code/typescript-default/src/components/icons/IconTooling.vue b/template/code/typescript-default/src/components/icons/IconTooling.vue deleted file mode 100644 index 660598d7c..000000000 --- a/template/code/typescript-default/src/components/icons/IconTooling.vue +++ /dev/null @@ -1,19 +0,0 @@ - - diff --git a/utils/renderEslint.ts b/utils/renderEslint.ts index dba489593..99549deaa 100644 --- a/utils/renderEslint.ts +++ b/utils/renderEslint.ts @@ -87,11 +87,11 @@ export default function renderEslint( } // update .vscode/extensions.json - const extensionsJsonPath = path.resolve(rootDir, '.vscode/extensions.json') + /*const extensionsJsonPath = path.resolve(rootDir, '.vscode/extensions.json') const existingExtensions = JSON.parse(fs.readFileSync(extensionsJsonPath, 'utf8')) existingExtensions.recommendations.push('dbaeumer.vscode-eslint') if (needsPrettier) { existingExtensions.recommendations.push('esbenp.prettier-vscode') } - fs.writeFileSync(extensionsJsonPath, JSON.stringify(existingExtensions, null, 2) + '\n', 'utf-8') + fs.writeFileSync(extensionsJsonPath, JSON.stringify(existingExtensions, null, 2) + '\n', 'utf-8')*/ } From c8f7dbc7b9e363a444f67c021250929f577207f4 Mon Sep 17 00:00:00 2001 From: meatjam <851404658@qq.com> Date: Sat, 17 Feb 2024 21:42:39 +0800 Subject: [PATCH 3/6] init (cherry picked from commit 68a2ec4b313ab76a507cbe7e5a3f088822b0ac6c) --- .gitignore | 2 + .idea/.gitignore | 5 + .idea/create-vue-customized.iml | 12 ++ .idea/markdown.xml | 9 ++ .idea/modules.xml | 8 + .idea/vcs.xml | 6 + media/screenshot-cli.png | Bin 432497 -> 0 bytes playground | 1 - playground/pinia-cypress/.gitignore | 30 ++++ playground/pinia-cypress/README.md | 51 ++++++ playground/pinia-cypress/cypress.config.js | 15 ++ .../pinia-cypress/cypress/e2e/example.cy.js | 8 + .../pinia-cypress/cypress/e2e/jsconfig.json | 8 + .../cypress/fixtures/example.json | 5 + .../pinia-cypress/cypress/support/commands.js | 25 +++ .../cypress/support/component-index.html | 12 ++ .../cypress/support/component.js | 30 ++++ .../pinia-cypress/cypress/support/e2e.js | 20 +++ playground/pinia-cypress/index.html | 13 ++ playground/pinia-cypress/jsconfig.json | 8 + playground/pinia-cypress/package.json | 25 +++ playground/pinia-cypress/public/favicon.ico | Bin 0 -> 4286 bytes playground/pinia-cypress/src/App.vue | 9 ++ playground/pinia-cypress/src/assets/logo.svg | 1 + playground/pinia-cypress/src/assets/main.css | 6 + .../src/components/__tests__/HelloWorld.cy.js | 12 ++ playground/pinia-cypress/src/main.js | 11 ++ .../pinia-cypress/src/stores/counter.js | 12 ++ playground/pinia-cypress/vite.config.js | 16 ++ playground/pinia-nightwatch/.gitignore | 33 ++++ .../pinia-nightwatch/.vscode/extensions.json | 3 + playground/pinia-nightwatch/README.md | 52 ++++++ playground/pinia-nightwatch/index.html | 13 ++ playground/pinia-nightwatch/jsconfig.json | 8 + .../pinia-nightwatch/nightwatch.conf.cjs | 153 ++++++++++++++++++ .../pinia-nightwatch/nightwatch/index.html | 16 ++ playground/pinia-nightwatch/package.json | 28 ++++ .../pinia-nightwatch/public/favicon.ico | Bin 0 -> 4286 bytes playground/pinia-nightwatch/src/App.vue | 9 ++ .../pinia-nightwatch/src/assets/logo.svg | 1 + .../pinia-nightwatch/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 14 ++ playground/pinia-nightwatch/src/main.js | 11 ++ .../pinia-nightwatch/src/stores/counter.js | 12 ++ .../pinia-nightwatch/tests/e2e/example.js | 11 ++ playground/pinia-nightwatch/vite.config.js | 20 +++ playground/pinia-playwright/.gitignore | 33 ++++ .../pinia-playwright/.vscode/extensions.json | 3 + playground/pinia-playwright/README.md | 48 ++++++ playground/pinia-playwright/e2e/vue.spec.js | 8 + playground/pinia-playwright/index.html | 13 ++ playground/pinia-playwright/jsconfig.json | 8 + playground/pinia-playwright/package.json | 21 +++ .../pinia-playwright/playwright.config.js | 110 +++++++++++++ .../pinia-playwright/public/favicon.ico | Bin 0 -> 4286 bytes playground/pinia-playwright/src/App.vue | 9 ++ .../pinia-playwright/src/assets/logo.svg | 1 + .../pinia-playwright/src/assets/main.css | 6 + playground/pinia-playwright/src/main.js | 11 ++ .../pinia-playwright/src/stores/counter.js | 12 ++ playground/pinia-playwright/vite.config.js | 16 ++ playground/pinia-vitest-cypress/.gitignore | 30 ++++ playground/pinia-vitest-cypress/README.md | 51 ++++++ .../pinia-vitest-cypress/cypress.config.js | 8 + .../cypress/e2e/example.cy.js | 8 + .../cypress/e2e/jsconfig.json | 8 + .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.js | 25 +++ .../cypress/support/e2e.js | 20 +++ playground/pinia-vitest-cypress/index.html | 13 ++ playground/pinia-vitest-cypress/jsconfig.json | 8 + playground/pinia-vitest-cypress/package.json | 27 ++++ .../pinia-vitest-cypress/public/favicon.ico | Bin 0 -> 4286 bytes playground/pinia-vitest-cypress/src/App.vue | 9 ++ .../pinia-vitest-cypress/src/assets/logo.svg | 1 + .../pinia-vitest-cypress/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ playground/pinia-vitest-cypress/src/main.js | 11 ++ .../src/stores/counter.js | 12 ++ .../pinia-vitest-cypress/vite.config.js | 16 ++ .../pinia-vitest-cypress/vitest.config.js | 14 ++ playground/pinia-vitest-nightwatch/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + playground/pinia-vitest-nightwatch/README.md | 58 +++++++ playground/pinia-vitest-nightwatch/index.html | 13 ++ .../pinia-vitest-nightwatch/jsconfig.json | 8 + .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../pinia-vitest-nightwatch/package.json | 30 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../pinia-vitest-nightwatch/src/App.vue | 9 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ .../pinia-vitest-nightwatch/src/main.js | 11 ++ .../src/stores/counter.js | 12 ++ .../tests/e2e/example.js | 11 ++ .../pinia-vitest-nightwatch/vite.config.js | 18 +++ .../pinia-vitest-nightwatch/vitest.config.js | 14 ++ playground/pinia-vitest-playwright/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + playground/pinia-vitest-playwright/README.md | 54 +++++++ .../pinia-vitest-playwright/e2e/vue.spec.js | 8 + playground/pinia-vitest-playwright/index.html | 13 ++ .../pinia-vitest-playwright/jsconfig.json | 8 + .../pinia-vitest-playwright/package.json | 25 +++ .../playwright.config.js | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../pinia-vitest-playwright/src/App.vue | 9 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ .../pinia-vitest-playwright/src/main.js | 11 ++ .../src/stores/counter.js | 12 ++ .../pinia-vitest-playwright/vite.config.js | 16 ++ .../pinia-vitest-playwright/vitest.config.js | 14 ++ playground/pinia-vitest/.gitignore | 30 ++++ playground/pinia-vitest/README.md | 35 ++++ playground/pinia-vitest/index.html | 13 ++ playground/pinia-vitest/jsconfig.json | 8 + playground/pinia-vitest/package.json | 23 +++ playground/pinia-vitest/public/favicon.ico | Bin 0 -> 4286 bytes playground/pinia-vitest/src/App.vue | 9 ++ playground/pinia-vitest/src/assets/logo.svg | 1 + playground/pinia-vitest/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ playground/pinia-vitest/src/main.js | 11 ++ playground/pinia-vitest/src/stores/counter.js | 12 ++ playground/pinia-vitest/vite.config.js | 16 ++ playground/pinia-vitest/vitest.config.js | 14 ++ playground/pinia-with-tests/.gitignore | 30 ++++ playground/pinia-with-tests/README.md | 51 ++++++ playground/pinia-with-tests/cypress.config.js | 8 + .../cypress/e2e/example.cy.js | 8 + .../cypress/e2e/jsconfig.json | 8 + .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.js | 25 +++ .../pinia-with-tests/cypress/support/e2e.js | 20 +++ playground/pinia-with-tests/index.html | 13 ++ playground/pinia-with-tests/jsconfig.json | 8 + playground/pinia-with-tests/package.json | 27 ++++ .../pinia-with-tests/public/favicon.ico | Bin 0 -> 4286 bytes playground/pinia-with-tests/src/App.vue | 9 ++ .../pinia-with-tests/src/assets/logo.svg | 1 + .../pinia-with-tests/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ playground/pinia-with-tests/src/main.js | 11 ++ .../pinia-with-tests/src/stores/counter.js | 12 ++ playground/pinia-with-tests/vite.config.js | 16 ++ playground/pinia-with-tests/vitest.config.js | 14 ++ playground/pinia/.gitignore | 30 ++++ playground/pinia/README.md | 29 ++++ playground/pinia/index.html | 13 ++ playground/pinia/jsconfig.json | 8 + playground/pinia/package.json | 19 +++ playground/pinia/public/favicon.ico | Bin 0 -> 4286 bytes playground/pinia/src/App.vue | 9 ++ playground/pinia/src/assets/logo.svg | 1 + playground/pinia/src/assets/main.css | 6 + playground/pinia/src/main.js | 11 ++ playground/pinia/src/stores/counter.js | 12 ++ playground/pinia/vite.config.js | 16 ++ playground/playwright/.gitignore | 33 ++++ playground/playwright/.vscode/extensions.json | 3 + playground/playwright/README.md | 48 ++++++ playground/playwright/e2e/vue.spec.js | 8 + playground/playwright/index.html | 13 ++ playground/playwright/jsconfig.json | 8 + playground/playwright/package.json | 20 +++ playground/playwright/playwright.config.js | 110 +++++++++++++ playground/playwright/public/favicon.ico | Bin 0 -> 4286 bytes playground/playwright/src/App.vue | 9 ++ playground/playwright/src/assets/logo.svg | 1 + playground/playwright/src/assets/main.css | 6 + playground/playwright/src/main.js | 6 + playground/playwright/vite.config.js | 16 ++ playground/router-cypress/.gitignore | 30 ++++ playground/router-cypress/README.md | 51 ++++++ playground/router-cypress/cypress.config.js | 15 ++ .../router-cypress/cypress/e2e/example.cy.js | 8 + .../router-cypress/cypress/e2e/jsconfig.json | 8 + .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.js | 25 +++ .../cypress/support/component-index.html | 12 ++ .../cypress/support/component.js | 30 ++++ .../router-cypress/cypress/support/e2e.js | 20 +++ playground/router-cypress/index.html | 13 ++ playground/router-cypress/jsconfig.json | 8 + playground/router-cypress/package.json | 25 +++ playground/router-cypress/public/favicon.ico | Bin 0 -> 4286 bytes playground/router-cypress/src/App.vue | 11 ++ playground/router-cypress/src/assets/logo.svg | 1 + playground/router-cypress/src/assets/main.css | 6 + .../src/components/__tests__/HelloWorld.cy.js | 12 ++ playground/router-cypress/src/main.js | 11 ++ playground/router-cypress/src/router/index.js | 15 ++ playground/router-cypress/src/views/Home.vue | 10 ++ playground/router-cypress/vite.config.js | 16 ++ playground/router-nightwatch/.gitignore | 33 ++++ .../router-nightwatch/.vscode/extensions.json | 3 + playground/router-nightwatch/README.md | 52 ++++++ playground/router-nightwatch/index.html | 13 ++ playground/router-nightwatch/jsconfig.json | 8 + .../router-nightwatch/nightwatch.conf.cjs | 153 ++++++++++++++++++ .../router-nightwatch/nightwatch/index.html | 16 ++ playground/router-nightwatch/package.json | 28 ++++ .../router-nightwatch/public/favicon.ico | Bin 0 -> 4286 bytes playground/router-nightwatch/src/App.vue | 11 ++ .../router-nightwatch/src/assets/logo.svg | 1 + .../router-nightwatch/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 14 ++ playground/router-nightwatch/src/main.js | 11 ++ .../router-nightwatch/src/router/index.js | 15 ++ .../router-nightwatch/src/views/Home.vue | 10 ++ .../router-nightwatch/tests/e2e/example.js | 11 ++ playground/router-nightwatch/vite.config.js | 20 +++ playground/router-pinia-cypress/.gitignore | 30 ++++ playground/router-pinia-cypress/README.md | 51 ++++++ .../router-pinia-cypress/cypress.config.js | 15 ++ .../cypress/e2e/example.cy.js | 8 + .../cypress/e2e/jsconfig.json | 8 + .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.js | 25 +++ .../cypress/support/component-index.html | 12 ++ .../cypress/support/component.js | 30 ++++ .../cypress/support/e2e.js | 20 +++ playground/router-pinia-cypress/index.html | 13 ++ playground/router-pinia-cypress/jsconfig.json | 8 + playground/router-pinia-cypress/package.json | 26 +++ .../router-pinia-cypress/public/favicon.ico | Bin 0 -> 4286 bytes playground/router-pinia-cypress/src/App.vue | 11 ++ .../router-pinia-cypress/src/assets/logo.svg | 1 + .../router-pinia-cypress/src/assets/main.css | 6 + .../src/components/__tests__/HelloWorld.cy.js | 12 ++ playground/router-pinia-cypress/src/main.js | 14 ++ .../router-pinia-cypress/src/router/index.js | 15 ++ .../src/stores/counter.js | 12 ++ .../router-pinia-cypress/src/views/Home.vue | 10 ++ .../router-pinia-cypress/vite.config.js | 16 ++ playground/router-pinia-nightwatch/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + playground/router-pinia-nightwatch/README.md | 52 ++++++ playground/router-pinia-nightwatch/index.html | 13 ++ .../router-pinia-nightwatch/jsconfig.json | 8 + .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../nightwatch/index.html | 16 ++ .../router-pinia-nightwatch/package.json | 29 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../router-pinia-nightwatch/src/App.vue | 11 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 14 ++ .../router-pinia-nightwatch/src/main.js | 14 ++ .../src/router/index.js | 15 ++ .../src/stores/counter.js | 12 ++ .../src/views/Home.vue | 10 ++ .../tests/e2e/example.js | 11 ++ .../router-pinia-nightwatch/vite.config.js | 20 +++ playground/router-pinia-playwright/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + playground/router-pinia-playwright/README.md | 48 ++++++ .../router-pinia-playwright/e2e/vue.spec.js | 8 + playground/router-pinia-playwright/index.html | 13 ++ .../router-pinia-playwright/jsconfig.json | 8 + .../router-pinia-playwright/package.json | 22 +++ .../playwright.config.js | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../router-pinia-playwright/src/App.vue | 11 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../router-pinia-playwright/src/main.js | 14 ++ .../src/router/index.js | 15 ++ .../src/stores/counter.js | 12 ++ .../src/views/Home.vue | 10 ++ .../router-pinia-playwright/vite.config.js | 16 ++ .../router-pinia-vitest-cypress/.gitignore | 30 ++++ .../router-pinia-vitest-cypress/README.md | 51 ++++++ .../cypress.config.js | 8 + .../cypress/e2e/example.cy.js | 8 + .../cypress/e2e/jsconfig.json | 8 + .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.js | 25 +++ .../cypress/support/e2e.js | 20 +++ .../router-pinia-vitest-cypress/index.html | 13 ++ .../router-pinia-vitest-cypress/jsconfig.json | 8 + .../router-pinia-vitest-cypress/package.json | 28 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../router-pinia-vitest-cypress/src/App.vue | 11 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ .../router-pinia-vitest-cypress/src/main.js | 14 ++ .../src/router/index.js | 15 ++ .../src/stores/counter.js | 12 ++ .../src/views/Home.vue | 10 ++ .../vite.config.js | 16 ++ .../vitest.config.js | 14 ++ .../router-pinia-vitest-nightwatch/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../router-pinia-vitest-nightwatch/README.md | 58 +++++++ .../router-pinia-vitest-nightwatch/index.html | 13 ++ .../jsconfig.json | 8 + .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../package.json | 31 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 11 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ .../src/main.js | 14 ++ .../src/router/index.js | 15 ++ .../src/stores/counter.js | 12 ++ .../src/views/Home.vue | 10 ++ .../tests/e2e/example.js | 11 ++ .../vite.config.js | 18 +++ .../vitest.config.js | 14 ++ .../router-pinia-vitest-playwright/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../router-pinia-vitest-playwright/README.md | 54 +++++++ .../e2e/vue.spec.js | 8 + .../router-pinia-vitest-playwright/index.html | 13 ++ .../jsconfig.json | 8 + .../package.json | 26 +++ .../playwright.config.js | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 11 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ .../src/main.js | 14 ++ .../src/router/index.js | 15 ++ .../src/stores/counter.js | 12 ++ .../src/views/Home.vue | 10 ++ .../vite.config.js | 16 ++ .../vitest.config.js | 14 ++ playground/router-pinia-vitest/.gitignore | 30 ++++ playground/router-pinia-vitest/README.md | 35 ++++ playground/router-pinia-vitest/index.html | 13 ++ playground/router-pinia-vitest/jsconfig.json | 8 + playground/router-pinia-vitest/package.json | 24 +++ .../router-pinia-vitest/public/favicon.ico | Bin 0 -> 4286 bytes playground/router-pinia-vitest/src/App.vue | 11 ++ .../router-pinia-vitest/src/assets/logo.svg | 1 + .../router-pinia-vitest/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ playground/router-pinia-vitest/src/main.js | 14 ++ .../router-pinia-vitest/src/router/index.js | 15 ++ .../router-pinia-vitest/src/stores/counter.js | 12 ++ .../router-pinia-vitest/src/views/Home.vue | 10 ++ playground/router-pinia-vitest/vite.config.js | 16 ++ .../router-pinia-vitest/vitest.config.js | 14 ++ playground/router-pinia-with-tests/.gitignore | 30 ++++ playground/router-pinia-with-tests/README.md | 51 ++++++ .../router-pinia-with-tests/cypress.config.js | 8 + .../cypress/e2e/example.cy.js | 8 + .../cypress/e2e/jsconfig.json | 8 + .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.js | 25 +++ .../cypress/support/e2e.js | 20 +++ playground/router-pinia-with-tests/index.html | 13 ++ .../router-pinia-with-tests/jsconfig.json | 8 + .../router-pinia-with-tests/package.json | 28 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../router-pinia-with-tests/src/App.vue | 11 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ .../router-pinia-with-tests/src/main.js | 14 ++ .../src/router/index.js | 15 ++ .../src/stores/counter.js | 12 ++ .../src/views/Home.vue | 10 ++ .../router-pinia-with-tests/vite.config.js | 16 ++ .../router-pinia-with-tests/vitest.config.js | 14 ++ playground/router-pinia/.gitignore | 30 ++++ playground/router-pinia/README.md | 29 ++++ playground/router-pinia/index.html | 13 ++ playground/router-pinia/jsconfig.json | 8 + playground/router-pinia/package.json | 20 +++ playground/router-pinia/public/favicon.ico | Bin 0 -> 4286 bytes playground/router-pinia/src/App.vue | 11 ++ playground/router-pinia/src/assets/logo.svg | 1 + playground/router-pinia/src/assets/main.css | 6 + playground/router-pinia/src/main.js | 14 ++ playground/router-pinia/src/router/index.js | 15 ++ playground/router-pinia/src/stores/counter.js | 12 ++ playground/router-pinia/src/views/Home.vue | 10 ++ playground/router-pinia/vite.config.js | 16 ++ playground/router-playwright/.gitignore | 33 ++++ .../router-playwright/.vscode/extensions.json | 3 + playground/router-playwright/README.md | 48 ++++++ playground/router-playwright/e2e/vue.spec.js | 8 + playground/router-playwright/index.html | 13 ++ playground/router-playwright/jsconfig.json | 8 + playground/router-playwright/package.json | 21 +++ .../router-playwright/playwright.config.js | 110 +++++++++++++ .../router-playwright/public/favicon.ico | Bin 0 -> 4286 bytes playground/router-playwright/src/App.vue | 11 ++ .../router-playwright/src/assets/logo.svg | 1 + .../router-playwright/src/assets/main.css | 6 + playground/router-playwright/src/main.js | 11 ++ .../router-playwright/src/router/index.js | 15 ++ .../router-playwright/src/views/Home.vue | 10 ++ playground/router-playwright/vite.config.js | 16 ++ playground/router-vitest-cypress/.gitignore | 30 ++++ playground/router-vitest-cypress/README.md | 51 ++++++ .../router-vitest-cypress/cypress.config.js | 8 + .../cypress/e2e/example.cy.js | 8 + .../cypress/e2e/jsconfig.json | 8 + .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.js | 25 +++ .../cypress/support/e2e.js | 20 +++ playground/router-vitest-cypress/index.html | 13 ++ .../router-vitest-cypress/jsconfig.json | 8 + playground/router-vitest-cypress/package.json | 27 ++++ .../router-vitest-cypress/public/favicon.ico | Bin 0 -> 4286 bytes playground/router-vitest-cypress/src/App.vue | 11 ++ .../router-vitest-cypress/src/assets/logo.svg | 1 + .../router-vitest-cypress/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ playground/router-vitest-cypress/src/main.js | 11 ++ .../router-vitest-cypress/src/router/index.js | 15 ++ .../router-vitest-cypress/src/views/Home.vue | 10 ++ .../router-vitest-cypress/vite.config.js | 16 ++ .../router-vitest-cypress/vitest.config.js | 14 ++ .../router-vitest-nightwatch/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + playground/router-vitest-nightwatch/README.md | 58 +++++++ .../router-vitest-nightwatch/index.html | 13 ++ .../router-vitest-nightwatch/jsconfig.json | 8 + .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../router-vitest-nightwatch/package.json | 30 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../router-vitest-nightwatch/src/App.vue | 11 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ .../router-vitest-nightwatch/src/main.js | 11 ++ .../src/router/index.js | 15 ++ .../src/views/Home.vue | 10 ++ .../tests/e2e/example.js | 11 ++ .../router-vitest-nightwatch/vite.config.js | 18 +++ .../router-vitest-nightwatch/vitest.config.js | 14 ++ .../router-vitest-playwright/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + playground/router-vitest-playwright/README.md | 54 +++++++ .../router-vitest-playwright/e2e/vue.spec.js | 8 + .../router-vitest-playwright/index.html | 13 ++ .../router-vitest-playwright/jsconfig.json | 8 + .../router-vitest-playwright/package.json | 25 +++ .../playwright.config.js | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../router-vitest-playwright/src/App.vue | 11 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ .../router-vitest-playwright/src/main.js | 11 ++ .../src/router/index.js | 15 ++ .../src/views/Home.vue | 10 ++ .../router-vitest-playwright/vite.config.js | 16 ++ .../router-vitest-playwright/vitest.config.js | 14 ++ playground/router-vitest/.gitignore | 30 ++++ playground/router-vitest/README.md | 35 ++++ playground/router-vitest/index.html | 13 ++ playground/router-vitest/jsconfig.json | 8 + playground/router-vitest/package.json | 23 +++ playground/router-vitest/public/favicon.ico | Bin 0 -> 4286 bytes playground/router-vitest/src/App.vue | 11 ++ playground/router-vitest/src/assets/logo.svg | 1 + playground/router-vitest/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ playground/router-vitest/src/main.js | 11 ++ playground/router-vitest/src/router/index.js | 15 ++ playground/router-vitest/src/views/Home.vue | 10 ++ playground/router-vitest/vite.config.js | 16 ++ playground/router-vitest/vitest.config.js | 14 ++ playground/router-with-tests/.gitignore | 30 ++++ playground/router-with-tests/README.md | 51 ++++++ .../router-with-tests/cypress.config.js | 8 + .../cypress/e2e/example.cy.js | 8 + .../cypress/e2e/jsconfig.json | 8 + .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.js | 25 +++ .../router-with-tests/cypress/support/e2e.js | 20 +++ playground/router-with-tests/index.html | 13 ++ playground/router-with-tests/jsconfig.json | 8 + playground/router-with-tests/package.json | 27 ++++ .../router-with-tests/public/favicon.ico | Bin 0 -> 4286 bytes playground/router-with-tests/src/App.vue | 11 ++ .../router-with-tests/src/assets/logo.svg | 1 + .../router-with-tests/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ playground/router-with-tests/src/main.js | 11 ++ .../router-with-tests/src/router/index.js | 15 ++ .../router-with-tests/src/views/Home.vue | 10 ++ playground/router-with-tests/vite.config.js | 16 ++ playground/router-with-tests/vitest.config.js | 14 ++ playground/router/.gitignore | 30 ++++ playground/router/README.md | 29 ++++ playground/router/index.html | 13 ++ playground/router/jsconfig.json | 8 + playground/router/package.json | 19 +++ playground/router/public/favicon.ico | Bin 0 -> 4286 bytes playground/router/src/App.vue | 11 ++ playground/router/src/assets/logo.svg | 1 + playground/router/src/assets/main.css | 6 + playground/router/src/main.js | 11 ++ playground/router/src/router/index.js | 15 ++ playground/router/src/views/Home.vue | 10 ++ playground/router/vite.config.js | 16 ++ playground/typescript-cypress/.gitignore | 30 ++++ playground/typescript-cypress/README.md | 62 +++++++ .../typescript-cypress/cypress.config.ts | 15 ++ .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/component-index.html | 12 ++ .../cypress/support/component.ts | 43 +++++ .../typescript-cypress/cypress/support/e2e.ts | 20 +++ playground/typescript-cypress/env.d.ts | 1 + playground/typescript-cypress/index.html | 13 ++ playground/typescript-cypress/package.json | 32 ++++ .../typescript-cypress/public/favicon.ico | Bin 0 -> 4286 bytes playground/typescript-cypress/src/App.vue | 10 ++ .../typescript-cypress/src/assets/logo.svg | 1 + .../typescript-cypress/src/assets/main.css | 6 + .../src/components/__tests__/HelloWorld.cy.ts | 12 ++ playground/typescript-cypress/src/main.ts | 6 + .../typescript-cypress/tsconfig.app.json | 14 ++ .../tsconfig.cypress-ct.json | 15 ++ playground/typescript-cypress/tsconfig.json | 17 ++ .../typescript-cypress/tsconfig.node.json | 19 +++ playground/typescript-cypress/vite.config.ts | 16 ++ playground/typescript-jsx-cypress/.gitignore | 30 ++++ playground/typescript-jsx-cypress/README.md | 62 +++++++ .../typescript-jsx-cypress/cypress.config.ts | 15 ++ .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/component-index.html | 12 ++ .../cypress/support/component.ts | 43 +++++ .../cypress/support/e2e.ts | 20 +++ playground/typescript-jsx-cypress/env.d.ts | 1 + playground/typescript-jsx-cypress/index.html | 13 ++ .../typescript-jsx-cypress/package.json | 33 ++++ .../typescript-jsx-cypress/public/favicon.ico | Bin 0 -> 4286 bytes playground/typescript-jsx-cypress/src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/__tests__/HelloWorld.cy.ts | 12 ++ playground/typescript-jsx-cypress/src/main.ts | 6 + .../typescript-jsx-cypress/tsconfig.app.json | 14 ++ .../tsconfig.cypress-ct.json | 15 ++ .../typescript-jsx-cypress/tsconfig.json | 17 ++ .../typescript-jsx-cypress/tsconfig.node.json | 19 +++ .../typescript-jsx-cypress/vite.config.ts | 18 +++ .../typescript-jsx-nightwatch/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../typescript-jsx-nightwatch/README.md | 63 ++++++++ playground/typescript-jsx-nightwatch/env.d.ts | 1 + .../typescript-jsx-nightwatch/index.html | 13 ++ .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../nightwatch/index.html | 16 ++ .../nightwatch/nightwatch.d.ts | 13 ++ .../nightwatch/tsconfig.json | 20 +++ .../typescript-jsx-nightwatch/package.json | 36 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-jsx-nightwatch/src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 14 ++ .../typescript-jsx-nightwatch/src/main.ts | 6 + .../tests/e2e/example.ts | 11 ++ .../tsconfig.app.json | 14 ++ .../typescript-jsx-nightwatch/tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../typescript-jsx-nightwatch/vite.config.ts | 22 +++ .../typescript-jsx-pinia-cypress/.gitignore | 30 ++++ .../typescript-jsx-pinia-cypress/README.md | 62 +++++++ .../cypress.config.ts | 15 ++ .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/component-index.html | 12 ++ .../cypress/support/component.ts | 43 +++++ .../cypress/support/e2e.ts | 20 +++ .../typescript-jsx-pinia-cypress/env.d.ts | 1 + .../typescript-jsx-pinia-cypress/index.html | 13 ++ .../typescript-jsx-pinia-cypress/package.json | 34 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-jsx-pinia-cypress/src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/__tests__/HelloWorld.cy.ts | 12 ++ .../typescript-jsx-pinia-cypress/src/main.ts | 11 ++ .../src/stores/counter.ts | 12 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.cypress-ct.json | 15 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../vite.config.ts | 18 +++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../typescript-jsx-pinia-nightwatch/README.md | 63 ++++++++ .../typescript-jsx-pinia-nightwatch/env.d.ts | 1 + .../index.html | 13 ++ .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../nightwatch/index.html | 16 ++ .../nightwatch/nightwatch.d.ts | 13 ++ .../nightwatch/tsconfig.json | 20 +++ .../package.json | 37 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 14 ++ .../src/main.ts | 11 ++ .../src/stores/counter.ts | 12 ++ .../tests/e2e/example.ts | 11 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../vite.config.ts | 22 +++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../typescript-jsx-pinia-playwright/README.md | 59 +++++++ .../e2e/tsconfig.json | 4 + .../e2e/vue.spec.ts | 8 + .../typescript-jsx-pinia-playwright/env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 30 ++++ .../playwright.config.ts | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/main.ts | 11 ++ .../src/stores/counter.ts | 12 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 11 ++ .../tsconfig.node.json | 19 +++ .../vite.config.ts | 18 +++ .../.gitignore | 30 ++++ .../README.md | 62 +++++++ .../cypress.config.ts | 8 + .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/e2e.ts | 20 +++ .../env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 37 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/main.ts | 11 ++ .../src/stores/counter.ts | 12 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 69 ++++++++ .../env.d.ts | 1 + .../index.html | 13 ++ .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../nightwatch/nightwatch.d.ts | 13 ++ .../nightwatch/tsconfig.json | 20 +++ .../package.json | 40 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/main.ts | 11 ++ .../src/stores/counter.ts | 12 ++ .../tests/e2e/example.ts | 11 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 20 +++ .../vitest.config.ts | 14 ++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 65 ++++++++ .../e2e/tsconfig.json | 4 + .../e2e/vue.spec.ts | 8 + .../env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 35 ++++ .../playwright.config.ts | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/main.ts | 11 ++ .../src/stores/counter.ts | 12 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ .../typescript-jsx-pinia-vitest/.gitignore | 30 ++++ .../typescript-jsx-pinia-vitest/README.md | 46 ++++++ .../typescript-jsx-pinia-vitest/env.d.ts | 1 + .../typescript-jsx-pinia-vitest/index.html | 13 ++ .../typescript-jsx-pinia-vitest/package.json | 33 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-jsx-pinia-vitest/src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../typescript-jsx-pinia-vitest/src/main.ts | 11 ++ .../src/stores/counter.ts | 12 ++ .../tsconfig.app.json | 14 ++ .../typescript-jsx-pinia-vitest/tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ .../.gitignore | 30 ++++ .../typescript-jsx-pinia-with-tests/README.md | 62 +++++++ .../cypress.config.ts | 8 + .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/e2e.ts | 20 +++ .../typescript-jsx-pinia-with-tests/env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 37 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/main.ts | 11 ++ .../src/stores/counter.ts | 12 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ playground/typescript-jsx-pinia/.gitignore | 30 ++++ playground/typescript-jsx-pinia/README.md | 40 +++++ playground/typescript-jsx-pinia/env.d.ts | 1 + playground/typescript-jsx-pinia/index.html | 13 ++ playground/typescript-jsx-pinia/package.json | 28 ++++ .../typescript-jsx-pinia/public/favicon.ico | Bin 0 -> 4286 bytes playground/typescript-jsx-pinia/src/App.vue | 10 ++ .../typescript-jsx-pinia/src/assets/logo.svg | 1 + .../typescript-jsx-pinia/src/assets/main.css | 6 + playground/typescript-jsx-pinia/src/main.ts | 11 ++ .../src/stores/counter.ts | 12 ++ .../typescript-jsx-pinia/tsconfig.app.json | 14 ++ playground/typescript-jsx-pinia/tsconfig.json | 11 ++ .../typescript-jsx-pinia/tsconfig.node.json | 19 +++ .../typescript-jsx-pinia/vite.config.ts | 18 +++ .../typescript-jsx-playwright/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../typescript-jsx-playwright/README.md | 59 +++++++ .../e2e/tsconfig.json | 4 + .../typescript-jsx-playwright/e2e/vue.spec.ts | 8 + playground/typescript-jsx-playwright/env.d.ts | 1 + .../typescript-jsx-playwright/index.html | 13 ++ .../typescript-jsx-playwright/package.json | 29 ++++ .../playwright.config.ts | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-jsx-playwright/src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../typescript-jsx-playwright/src/main.ts | 6 + .../tsconfig.app.json | 14 ++ .../typescript-jsx-playwright/tsconfig.json | 11 ++ .../tsconfig.node.json | 19 +++ .../typescript-jsx-playwright/vite.config.ts | 18 +++ .../typescript-jsx-router-cypress/.gitignore | 30 ++++ .../typescript-jsx-router-cypress/README.md | 62 +++++++ .../cypress.config.ts | 15 ++ .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/component-index.html | 12 ++ .../cypress/support/component.ts | 43 +++++ .../cypress/support/e2e.ts | 20 +++ .../typescript-jsx-router-cypress/env.d.ts | 1 + .../typescript-jsx-router-cypress/index.html | 13 ++ .../package.json | 34 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-jsx-router-cypress/src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../src/components/__tests__/HelloWorld.cy.ts | 12 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../typescript-jsx-router-cypress/src/main.ts | 11 ++ .../src/router/index.ts | 23 +++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.cypress-ct.json | 15 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../vite.config.ts | 18 +++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 63 ++++++++ .../typescript-jsx-router-nightwatch/env.d.ts | 1 + .../index.html | 13 ++ .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../nightwatch/index.html | 16 ++ .../nightwatch/nightwatch.d.ts | 13 ++ .../nightwatch/tsconfig.json | 20 +++ .../package.json | 37 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 14 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 11 ++ .../src/router/index.ts | 23 +++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tests/e2e/example.ts | 11 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../vite.config.ts | 22 +++ .../.gitignore | 30 ++++ .../README.md | 62 +++++++ .../cypress.config.ts | 15 ++ .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/component-index.html | 12 ++ .../cypress/support/component.ts | 43 +++++ .../cypress/support/e2e.ts | 20 +++ .../env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 35 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../src/components/__tests__/HelloWorld.cy.ts | 12 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.cypress-ct.json | 15 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../vite.config.ts | 18 +++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 63 ++++++++ .../env.d.ts | 1 + .../index.html | 13 ++ .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../nightwatch/index.html | 16 ++ .../nightwatch/nightwatch.d.ts | 13 ++ .../nightwatch/tsconfig.json | 20 +++ .../package.json | 38 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 14 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tests/e2e/example.ts | 11 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../vite.config.ts | 22 +++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 59 +++++++ .../e2e/tsconfig.json | 4 + .../e2e/vue.spec.ts | 8 + .../env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 31 ++++ .../playwright.config.ts | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 11 ++ .../tsconfig.node.json | 19 +++ .../vite.config.ts | 18 +++ .../.gitignore | 30 ++++ .../README.md | 62 +++++++ .../cypress.config.ts | 8 + .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/e2e.ts | 20 +++ .../env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 38 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 69 ++++++++ .../env.d.ts | 1 + .../index.html | 13 ++ .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../nightwatch/nightwatch.d.ts | 13 ++ .../nightwatch/tsconfig.json | 20 +++ .../package.json | 41 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tests/e2e/example.ts | 11 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 20 +++ .../vitest.config.ts | 14 ++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 65 ++++++++ .../e2e/tsconfig.json | 4 + .../e2e/vue.spec.ts | 8 + .../env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 36 +++++ .../playwright.config.ts | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ .../.gitignore | 30 ++++ .../README.md | 46 ++++++ .../env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 34 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ .../.gitignore | 30 ++++ .../README.md | 62 +++++++ .../cypress.config.ts | 8 + .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/e2e.ts | 20 +++ .../env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 38 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ .../typescript-jsx-router-pinia/.gitignore | 30 ++++ .../typescript-jsx-router-pinia/README.md | 40 +++++ .../typescript-jsx-router-pinia/env.d.ts | 1 + .../typescript-jsx-router-pinia/index.html | 13 ++ .../typescript-jsx-router-pinia/package.json | 29 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-jsx-router-pinia/src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../typescript-jsx-router-pinia/src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../typescript-jsx-router-pinia/tsconfig.json | 11 ++ .../tsconfig.node.json | 19 +++ .../vite.config.ts | 18 +++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 59 +++++++ .../e2e/tsconfig.json | 4 + .../e2e/vue.spec.ts | 8 + .../typescript-jsx-router-playwright/env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 30 ++++ .../playwright.config.ts | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 11 ++ .../src/router/index.ts | 23 +++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 11 ++ .../tsconfig.node.json | 19 +++ .../vite.config.ts | 18 +++ .../.gitignore | 30 ++++ .../README.md | 62 +++++++ .../cypress.config.ts | 8 + .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/e2e.ts | 20 +++ .../env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 37 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 11 ++ .../src/router/index.ts | 23 +++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 69 ++++++++ .../env.d.ts | 1 + .../index.html | 13 ++ .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../nightwatch/nightwatch.d.ts | 13 ++ .../nightwatch/tsconfig.json | 20 +++ .../package.json | 40 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 11 ++ .../src/router/index.ts | 23 +++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tests/e2e/example.ts | 11 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 20 +++ .../vitest.config.ts | 14 ++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 65 ++++++++ .../e2e/tsconfig.json | 4 + .../e2e/vue.spec.ts | 8 + .../env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 35 ++++ .../playwright.config.ts | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 11 ++ .../src/router/index.ts | 23 +++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ .../typescript-jsx-router-vitest/.gitignore | 30 ++++ .../typescript-jsx-router-vitest/README.md | 46 ++++++ .../typescript-jsx-router-vitest/env.d.ts | 1 + .../typescript-jsx-router-vitest/index.html | 13 ++ .../typescript-jsx-router-vitest/package.json | 33 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-jsx-router-vitest/src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../typescript-jsx-router-vitest/src/main.ts | 11 ++ .../src/router/index.ts | 23 +++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ .../.gitignore | 30 ++++ .../README.md | 62 +++++++ .../cypress.config.ts | 8 + .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/e2e.ts | 20 +++ .../typescript-jsx-router-with-tests/env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 37 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 11 ++ .../src/router/index.ts | 23 +++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ playground/typescript-jsx-router/.gitignore | 30 ++++ playground/typescript-jsx-router/README.md | 40 +++++ playground/typescript-jsx-router/env.d.ts | 1 + playground/typescript-jsx-router/index.html | 13 ++ playground/typescript-jsx-router/package.json | 28 ++++ .../typescript-jsx-router/public/favicon.ico | Bin 0 -> 4286 bytes playground/typescript-jsx-router/src/App.vue | 85 ++++++++++ .../typescript-jsx-router/src/assets/logo.svg | 1 + .../typescript-jsx-router/src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ playground/typescript-jsx-router/src/main.ts | 11 ++ .../typescript-jsx-router/src/router/index.ts | 23 +++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../typescript-jsx-router/tsconfig.app.json | 14 ++ .../typescript-jsx-router/tsconfig.json | 11 ++ .../typescript-jsx-router/tsconfig.node.json | 19 +++ .../typescript-jsx-router/vite.config.ts | 18 +++ .../typescript-jsx-vitest-cypress/.gitignore | 30 ++++ .../typescript-jsx-vitest-cypress/README.md | 62 +++++++ .../cypress.config.ts | 8 + .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/e2e.ts | 20 +++ .../typescript-jsx-vitest-cypress/env.d.ts | 1 + .../typescript-jsx-vitest-cypress/index.html | 13 ++ .../package.json | 36 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-jsx-vitest-cypress/src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../typescript-jsx-vitest-cypress/src/main.ts | 6 + .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 69 ++++++++ .../typescript-jsx-vitest-nightwatch/env.d.ts | 1 + .../index.html | 13 ++ .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../nightwatch/nightwatch.d.ts | 13 ++ .../nightwatch/tsconfig.json | 20 +++ .../package.json | 39 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/main.ts | 6 + .../tests/e2e/example.ts | 11 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 20 +++ .../vitest.config.ts | 14 ++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 65 ++++++++ .../e2e/tsconfig.json | 4 + .../e2e/vue.spec.ts | 8 + .../typescript-jsx-vitest-playwright/env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 34 ++++ .../playwright.config.ts | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/main.ts | 6 + .../tsconfig.app.json | 14 ++ .../tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ playground/typescript-jsx-vitest/.gitignore | 30 ++++ playground/typescript-jsx-vitest/README.md | 46 ++++++ playground/typescript-jsx-vitest/env.d.ts | 1 + playground/typescript-jsx-vitest/index.html | 13 ++ playground/typescript-jsx-vitest/package.json | 32 ++++ .../typescript-jsx-vitest/public/favicon.ico | Bin 0 -> 4286 bytes playground/typescript-jsx-vitest/src/App.vue | 10 ++ .../typescript-jsx-vitest/src/assets/logo.svg | 1 + .../typescript-jsx-vitest/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ playground/typescript-jsx-vitest/src/main.ts | 6 + .../typescript-jsx-vitest/tsconfig.app.json | 14 ++ .../typescript-jsx-vitest/tsconfig.json | 14 ++ .../typescript-jsx-vitest/tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../typescript-jsx-vitest/vite.config.ts | 18 +++ .../typescript-jsx-vitest/vitest.config.ts | 14 ++ .../typescript-jsx-with-tests/.gitignore | 30 ++++ .../typescript-jsx-with-tests/README.md | 62 +++++++ .../cypress.config.ts | 8 + .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/e2e.ts | 20 +++ playground/typescript-jsx-with-tests/env.d.ts | 1 + .../typescript-jsx-with-tests/index.html | 13 ++ .../typescript-jsx-with-tests/package.json | 36 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-jsx-with-tests/src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../typescript-jsx-with-tests/src/main.ts | 6 + .../tsconfig.app.json | 14 ++ .../typescript-jsx-with-tests/tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../typescript-jsx-with-tests/vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ playground/typescript-jsx/.gitignore | 30 ++++ playground/typescript-jsx/README.md | 40 +++++ playground/typescript-jsx/env.d.ts | 1 + playground/typescript-jsx/index.html | 13 ++ playground/typescript-jsx/package.json | 27 ++++ playground/typescript-jsx/public/favicon.ico | Bin 0 -> 4286 bytes playground/typescript-jsx/src/App.vue | 10 ++ playground/typescript-jsx/src/assets/logo.svg | 1 + playground/typescript-jsx/src/assets/main.css | 6 + playground/typescript-jsx/src/main.ts | 6 + playground/typescript-jsx/tsconfig.app.json | 14 ++ playground/typescript-jsx/tsconfig.json | 11 ++ playground/typescript-jsx/tsconfig.node.json | 19 +++ playground/typescript-jsx/vite.config.ts | 18 +++ playground/typescript-nightwatch/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + playground/typescript-nightwatch/README.md | 63 ++++++++ playground/typescript-nightwatch/env.d.ts | 1 + playground/typescript-nightwatch/index.html | 13 ++ .../typescript-nightwatch/nightwatch.conf.cjs | 153 ++++++++++++++++++ .../nightwatch/index.html | 16 ++ .../nightwatch/nightwatch.d.ts | 13 ++ .../nightwatch/tsconfig.json | 20 +++ playground/typescript-nightwatch/package.json | 35 ++++ .../typescript-nightwatch/public/favicon.ico | Bin 0 -> 4286 bytes playground/typescript-nightwatch/src/App.vue | 10 ++ .../typescript-nightwatch/src/assets/logo.svg | 1 + .../typescript-nightwatch/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 14 ++ playground/typescript-nightwatch/src/main.ts | 6 + .../tests/e2e/example.ts | 11 ++ .../typescript-nightwatch/tsconfig.app.json | 14 ++ .../typescript-nightwatch/tsconfig.json | 14 ++ .../typescript-nightwatch/tsconfig.node.json | 19 +++ .../typescript-nightwatch/vite.config.ts | 20 +++ .../typescript-pinia-cypress/.gitignore | 30 ++++ playground/typescript-pinia-cypress/README.md | 62 +++++++ .../cypress.config.ts | 15 ++ .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/component-index.html | 12 ++ .../cypress/support/component.ts | 43 +++++ .../cypress/support/e2e.ts | 20 +++ playground/typescript-pinia-cypress/env.d.ts | 1 + .../typescript-pinia-cypress/index.html | 13 ++ .../typescript-pinia-cypress/package.json | 33 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-pinia-cypress/src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/__tests__/HelloWorld.cy.ts | 12 ++ .../typescript-pinia-cypress/src/main.ts | 11 ++ .../src/stores/counter.ts | 12 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.cypress-ct.json | 15 ++ .../typescript-pinia-cypress/tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../typescript-pinia-cypress/vite.config.ts | 16 ++ .../typescript-pinia-nightwatch/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../typescript-pinia-nightwatch/README.md | 63 ++++++++ .../typescript-pinia-nightwatch/env.d.ts | 1 + .../typescript-pinia-nightwatch/index.html | 13 ++ .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../nightwatch/index.html | 16 ++ .../nightwatch/nightwatch.d.ts | 13 ++ .../nightwatch/tsconfig.json | 20 +++ .../typescript-pinia-nightwatch/package.json | 36 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-pinia-nightwatch/src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 14 ++ .../typescript-pinia-nightwatch/src/main.ts | 11 ++ .../src/stores/counter.ts | 12 ++ .../tests/e2e/example.ts | 11 ++ .../tsconfig.app.json | 14 ++ .../typescript-pinia-nightwatch/tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../vite.config.ts | 20 +++ .../typescript-pinia-playwright/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../typescript-pinia-playwright/README.md | 59 +++++++ .../e2e/tsconfig.json | 4 + .../e2e/vue.spec.ts | 8 + .../typescript-pinia-playwright/env.d.ts | 1 + .../typescript-pinia-playwright/index.html | 13 ++ .../typescript-pinia-playwright/package.json | 29 ++++ .../playwright.config.ts | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-pinia-playwright/src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../typescript-pinia-playwright/src/main.ts | 11 ++ .../src/stores/counter.ts | 12 ++ .../tsconfig.app.json | 14 ++ .../typescript-pinia-playwright/tsconfig.json | 11 ++ .../tsconfig.node.json | 19 +++ .../vite.config.ts | 16 ++ .../.gitignore | 30 ++++ .../typescript-pinia-vitest-cypress/README.md | 62 +++++++ .../cypress.config.ts | 8 + .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/e2e.ts | 20 +++ .../typescript-pinia-vitest-cypress/env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 36 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/main.ts | 11 ++ .../src/stores/counter.ts | 12 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 16 ++ .../vitest.config.ts | 14 ++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 69 ++++++++ .../env.d.ts | 1 + .../index.html | 13 ++ .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../nightwatch/nightwatch.d.ts | 13 ++ .../nightwatch/tsconfig.json | 20 +++ .../package.json | 39 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/main.ts | 11 ++ .../src/stores/counter.ts | 12 ++ .../tests/e2e/example.ts | 11 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 65 ++++++++ .../e2e/tsconfig.json | 4 + .../e2e/vue.spec.ts | 8 + .../env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 34 ++++ .../playwright.config.ts | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/main.ts | 11 ++ .../src/stores/counter.ts | 12 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 16 ++ .../vitest.config.ts | 14 ++ playground/typescript-pinia-vitest/.gitignore | 30 ++++ playground/typescript-pinia-vitest/README.md | 46 ++++++ playground/typescript-pinia-vitest/env.d.ts | 1 + playground/typescript-pinia-vitest/index.html | 13 ++ .../typescript-pinia-vitest/package.json | 32 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-pinia-vitest/src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../typescript-pinia-vitest/src/main.ts | 11 ++ .../src/stores/counter.ts | 12 ++ .../typescript-pinia-vitest/tsconfig.app.json | 14 ++ .../typescript-pinia-vitest/tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../typescript-pinia-vitest/vite.config.ts | 16 ++ .../typescript-pinia-vitest/vitest.config.ts | 14 ++ .../typescript-pinia-with-tests/.gitignore | 30 ++++ .../typescript-pinia-with-tests/README.md | 62 +++++++ .../cypress.config.ts | 8 + .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/e2e.ts | 20 +++ .../typescript-pinia-with-tests/env.d.ts | 1 + .../typescript-pinia-with-tests/index.html | 13 ++ .../typescript-pinia-with-tests/package.json | 36 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-pinia-with-tests/src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../typescript-pinia-with-tests/src/main.ts | 11 ++ .../src/stores/counter.ts | 12 ++ .../tsconfig.app.json | 14 ++ .../typescript-pinia-with-tests/tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 16 ++ .../vitest.config.ts | 14 ++ playground/typescript-pinia/.gitignore | 30 ++++ playground/typescript-pinia/README.md | 40 +++++ playground/typescript-pinia/env.d.ts | 1 + playground/typescript-pinia/index.html | 13 ++ playground/typescript-pinia/package.json | 27 ++++ .../typescript-pinia/public/favicon.ico | Bin 0 -> 4286 bytes playground/typescript-pinia/src/App.vue | 10 ++ .../typescript-pinia/src/assets/logo.svg | 1 + .../typescript-pinia/src/assets/main.css | 6 + playground/typescript-pinia/src/main.ts | 11 ++ .../typescript-pinia/src/stores/counter.ts | 12 ++ playground/typescript-pinia/tsconfig.app.json | 14 ++ playground/typescript-pinia/tsconfig.json | 11 ++ .../typescript-pinia/tsconfig.node.json | 19 +++ playground/typescript-pinia/vite.config.ts | 16 ++ playground/typescript-playwright/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + playground/typescript-playwright/README.md | 59 +++++++ .../typescript-playwright/e2e/tsconfig.json | 4 + .../typescript-playwright/e2e/vue.spec.ts | 8 + playground/typescript-playwright/env.d.ts | 1 + playground/typescript-playwright/index.html | 13 ++ playground/typescript-playwright/package.json | 28 ++++ .../playwright.config.ts | 110 +++++++++++++ .../typescript-playwright/public/favicon.ico | Bin 0 -> 4286 bytes playground/typescript-playwright/src/App.vue | 10 ++ .../typescript-playwright/src/assets/logo.svg | 1 + .../typescript-playwright/src/assets/main.css | 6 + playground/typescript-playwright/src/main.ts | 6 + .../typescript-playwright/tsconfig.app.json | 14 ++ .../typescript-playwright/tsconfig.json | 11 ++ .../typescript-playwright/tsconfig.node.json | 19 +++ .../typescript-playwright/vite.config.ts | 16 ++ .../typescript-router-cypress/.gitignore | 30 ++++ .../typescript-router-cypress/README.md | 62 +++++++ .../cypress.config.ts | 15 ++ .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/component-index.html | 12 ++ .../cypress/support/component.ts | 43 +++++ .../cypress/support/e2e.ts | 20 +++ playground/typescript-router-cypress/env.d.ts | 1 + .../typescript-router-cypress/index.html | 13 ++ .../typescript-router-cypress/package.json | 33 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-router-cypress/src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../src/components/__tests__/HelloWorld.cy.ts | 12 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../typescript-router-cypress/src/main.ts | 11 ++ .../src/router/index.ts | 23 +++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.cypress-ct.json | 15 ++ .../typescript-router-cypress/tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../typescript-router-cypress/vite.config.ts | 16 ++ .../typescript-router-nightwatch/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../typescript-router-nightwatch/README.md | 63 ++++++++ .../typescript-router-nightwatch/env.d.ts | 1 + .../typescript-router-nightwatch/index.html | 13 ++ .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../nightwatch/index.html | 16 ++ .../nightwatch/nightwatch.d.ts | 13 ++ .../nightwatch/tsconfig.json | 20 +++ .../typescript-router-nightwatch/package.json | 36 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-router-nightwatch/src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 14 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../typescript-router-nightwatch/src/main.ts | 11 ++ .../src/router/index.ts | 23 +++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tests/e2e/example.ts | 11 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../vite.config.ts | 20 +++ .../.gitignore | 30 ++++ .../typescript-router-pinia-cypress/README.md | 62 +++++++ .../cypress.config.ts | 15 ++ .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/component-index.html | 12 ++ .../cypress/support/component.ts | 43 +++++ .../cypress/support/e2e.ts | 20 +++ .../typescript-router-pinia-cypress/env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 34 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../src/components/__tests__/HelloWorld.cy.ts | 12 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.cypress-ct.json | 15 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../vite.config.ts | 16 ++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 63 ++++++++ .../env.d.ts | 1 + .../index.html | 13 ++ .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../nightwatch/index.html | 16 ++ .../nightwatch/nightwatch.d.ts | 13 ++ .../nightwatch/tsconfig.json | 20 +++ .../package.json | 37 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 14 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tests/e2e/example.ts | 11 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../vite.config.ts | 20 +++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 59 +++++++ .../e2e/tsconfig.json | 4 + .../e2e/vue.spec.ts | 8 + .../env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 30 ++++ .../playwright.config.ts | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 11 ++ .../tsconfig.node.json | 19 +++ .../vite.config.ts | 16 ++ .../.gitignore | 30 ++++ .../README.md | 62 +++++++ .../cypress.config.ts | 8 + .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/e2e.ts | 20 +++ .../env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 37 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 16 ++ .../vitest.config.ts | 14 ++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 69 ++++++++ .../env.d.ts | 1 + .../index.html | 13 ++ .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../nightwatch/nightwatch.d.ts | 13 ++ .../nightwatch/tsconfig.json | 20 +++ .../package.json | 40 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tests/e2e/example.ts | 11 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 65 ++++++++ .../e2e/tsconfig.json | 4 + .../e2e/vue.spec.ts | 8 + .../env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 35 ++++ .../playwright.config.ts | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 16 ++ .../vitest.config.ts | 14 ++ .../typescript-router-pinia-vitest/.gitignore | 30 ++++ .../typescript-router-pinia-vitest/README.md | 46 ++++++ .../typescript-router-pinia-vitest/env.d.ts | 1 + .../typescript-router-pinia-vitest/index.html | 13 ++ .../package.json | 33 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 16 ++ .../vitest.config.ts | 14 ++ .../.gitignore | 30 ++++ .../README.md | 62 +++++++ .../cypress.config.ts | 8 + .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/e2e.ts | 20 +++ .../env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 37 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 16 ++ .../vitest.config.ts | 14 ++ playground/typescript-router-pinia/.gitignore | 30 ++++ playground/typescript-router-pinia/README.md | 40 +++++ playground/typescript-router-pinia/env.d.ts | 1 + playground/typescript-router-pinia/index.html | 13 ++ .../typescript-router-pinia/package.json | 28 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-router-pinia/src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../typescript-router-pinia/src/main.ts | 14 ++ .../src/router/index.ts | 23 +++ .../src/stores/counter.ts | 12 ++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../typescript-router-pinia/tsconfig.app.json | 14 ++ .../typescript-router-pinia/tsconfig.json | 11 ++ .../tsconfig.node.json | 19 +++ .../typescript-router-pinia/vite.config.ts | 16 ++ .../typescript-router-playwright/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../typescript-router-playwright/README.md | 59 +++++++ .../e2e/tsconfig.json | 4 + .../e2e/vue.spec.ts | 8 + .../typescript-router-playwright/env.d.ts | 1 + .../typescript-router-playwright/index.html | 13 ++ .../typescript-router-playwright/package.json | 29 ++++ .../playwright.config.ts | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-router-playwright/src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../typescript-router-playwright/src/main.ts | 11 ++ .../src/router/index.ts | 23 +++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 11 ++ .../tsconfig.node.json | 19 +++ .../vite.config.ts | 16 ++ .../.gitignore | 30 ++++ .../README.md | 62 +++++++ .../cypress.config.ts | 8 + .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/e2e.ts | 20 +++ .../typescript-router-vitest-cypress/env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 36 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 11 ++ .../src/router/index.ts | 23 +++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 16 ++ .../vitest.config.ts | 14 ++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 69 ++++++++ .../env.d.ts | 1 + .../index.html | 13 ++ .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../nightwatch/nightwatch.d.ts | 13 ++ .../nightwatch/tsconfig.json | 20 +++ .../package.json | 39 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 11 ++ .../src/router/index.ts | 23 +++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tests/e2e/example.ts | 11 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ .../.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../README.md | 65 ++++++++ .../e2e/tsconfig.json | 4 + .../e2e/vue.spec.ts | 8 + .../env.d.ts | 1 + .../index.html | 13 ++ .../package.json | 34 ++++ .../playwright.config.ts | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../src/main.ts | 11 ++ .../src/router/index.ts | 23 +++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 16 ++ .../vitest.config.ts | 14 ++ .../typescript-router-vitest/.gitignore | 30 ++++ playground/typescript-router-vitest/README.md | 46 ++++++ playground/typescript-router-vitest/env.d.ts | 1 + .../typescript-router-vitest/index.html | 13 ++ .../typescript-router-vitest/package.json | 32 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-router-vitest/src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../typescript-router-vitest/src/main.ts | 11 ++ .../src/router/index.ts | 23 +++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../typescript-router-vitest/tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../typescript-router-vitest/vite.config.ts | 16 ++ .../typescript-router-vitest/vitest.config.ts | 14 ++ .../typescript-router-with-tests/.gitignore | 30 ++++ .../typescript-router-with-tests/README.md | 62 +++++++ .../cypress.config.ts | 8 + .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/e2e.ts | 20 +++ .../typescript-router-with-tests/env.d.ts | 1 + .../typescript-router-with-tests/index.html | 13 ++ .../typescript-router-with-tests/package.json | 36 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-router-with-tests/src/App.vue | 85 ++++++++++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ .../typescript-router-with-tests/src/main.ts | 11 ++ .../src/router/index.ts | 23 +++ .../src/views/AboutView.vue | 15 ++ .../src/views/HomeView.vue | 9 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 16 ++ .../vitest.config.ts | 14 ++ playground/typescript-router/.gitignore | 30 ++++ playground/typescript-router/README.md | 40 +++++ playground/typescript-router/env.d.ts | 1 + playground/typescript-router/index.html | 13 ++ playground/typescript-router/package.json | 27 ++++ .../typescript-router/public/favicon.ico | Bin 0 -> 4286 bytes playground/typescript-router/src/App.vue | 85 ++++++++++ .../typescript-router/src/assets/logo.svg | 1 + .../typescript-router/src/assets/main.css | 6 + .../src/components/HelloWorld.vue | 41 +++++ .../src/components/TheWelcome.vue | 88 ++++++++++ .../src/components/WelcomeItem.vue | 87 ++++++++++ .../src/components/icons/IconCommunity.vue | 7 + .../components/icons/IconDocumentation.vue | 7 + .../src/components/icons/IconEcosystem.vue | 7 + .../src/components/icons/IconSupport.vue | 7 + .../src/components/icons/IconTooling.vue | 19 +++ playground/typescript-router/src/main.ts | 11 ++ .../typescript-router/src/router/index.ts | 23 +++ .../typescript-router/src/views/AboutView.vue | 15 ++ .../typescript-router/src/views/HomeView.vue | 9 ++ .../typescript-router/tsconfig.app.json | 14 ++ playground/typescript-router/tsconfig.json | 11 ++ .../typescript-router/tsconfig.node.json | 19 +++ playground/typescript-router/vite.config.ts | 16 ++ .../typescript-vitest-cypress/.gitignore | 30 ++++ .../typescript-vitest-cypress/README.md | 62 +++++++ .../cypress.config.ts | 8 + .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/e2e.ts | 20 +++ playground/typescript-vitest-cypress/env.d.ts | 1 + .../typescript-vitest-cypress/index.html | 13 ++ .../typescript-vitest-cypress/package.json | 35 ++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-vitest-cypress/src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../typescript-vitest-cypress/src/main.ts | 6 + .../tsconfig.app.json | 14 ++ .../typescript-vitest-cypress/tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../typescript-vitest-cypress/vite.config.ts | 16 ++ .../vitest.config.ts | 14 ++ .../typescript-vitest-nightwatch/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../typescript-vitest-nightwatch/README.md | 69 ++++++++ .../typescript-vitest-nightwatch/env.d.ts | 1 + .../typescript-vitest-nightwatch/index.html | 13 ++ .../nightwatch.conf.cjs | 153 ++++++++++++++++++ .../nightwatch/nightwatch.d.ts | 13 ++ .../nightwatch/tsconfig.json | 20 +++ .../typescript-vitest-nightwatch/package.json | 38 +++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-vitest-nightwatch/src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../typescript-vitest-nightwatch/src/main.ts | 6 + .../tests/e2e/example.ts | 11 ++ .../tsconfig.app.json | 14 ++ .../tsconfig.json | 17 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 18 +++ .../vitest.config.ts | 14 ++ .../typescript-vitest-playwright/.gitignore | 33 ++++ .../.vscode/extensions.json | 3 + .../typescript-vitest-playwright/README.md | 65 ++++++++ .../e2e/tsconfig.json | 4 + .../e2e/vue.spec.ts | 8 + .../typescript-vitest-playwright/env.d.ts | 1 + .../typescript-vitest-playwright/index.html | 13 ++ .../typescript-vitest-playwright/package.json | 33 ++++ .../playwright.config.ts | 110 +++++++++++++ .../public/favicon.ico | Bin 0 -> 4286 bytes .../typescript-vitest-playwright/src/App.vue | 10 ++ .../src/assets/logo.svg | 1 + .../src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ .../typescript-vitest-playwright/src/main.ts | 6 + .../tsconfig.app.json | 14 ++ .../tsconfig.json | 14 ++ .../tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../vite.config.ts | 16 ++ .../vitest.config.ts | 14 ++ playground/typescript-vitest/.gitignore | 30 ++++ playground/typescript-vitest/README.md | 46 ++++++ playground/typescript-vitest/env.d.ts | 1 + playground/typescript-vitest/index.html | 13 ++ playground/typescript-vitest/package.json | 31 ++++ .../typescript-vitest/public/favicon.ico | Bin 0 -> 4286 bytes playground/typescript-vitest/src/App.vue | 10 ++ .../typescript-vitest/src/assets/logo.svg | 1 + .../typescript-vitest/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ playground/typescript-vitest/src/main.ts | 6 + .../typescript-vitest/tsconfig.app.json | 14 ++ playground/typescript-vitest/tsconfig.json | 14 ++ .../typescript-vitest/tsconfig.node.json | 19 +++ .../typescript-vitest/tsconfig.vitest.json | 11 ++ playground/typescript-vitest/vite.config.ts | 16 ++ playground/typescript-vitest/vitest.config.ts | 14 ++ playground/typescript-with-tests/.gitignore | 30 ++++ playground/typescript-with-tests/README.md | 62 +++++++ .../typescript-with-tests/cypress.config.ts | 8 + .../cypress/e2e/example.cy.ts | 8 + .../cypress/e2e/tsconfig.json | 10 ++ .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.ts | 39 +++++ .../cypress/support/e2e.ts | 20 +++ playground/typescript-with-tests/env.d.ts | 1 + playground/typescript-with-tests/index.html | 13 ++ playground/typescript-with-tests/package.json | 35 ++++ .../typescript-with-tests/public/favicon.ico | Bin 0 -> 4286 bytes playground/typescript-with-tests/src/App.vue | 10 ++ .../typescript-with-tests/src/assets/logo.svg | 1 + .../typescript-with-tests/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.ts | 11 ++ playground/typescript-with-tests/src/main.ts | 6 + .../typescript-with-tests/tsconfig.app.json | 14 ++ .../typescript-with-tests/tsconfig.json | 17 ++ .../typescript-with-tests/tsconfig.node.json | 19 +++ .../tsconfig.vitest.json | 11 ++ .../typescript-with-tests/vite.config.ts | 16 ++ .../typescript-with-tests/vitest.config.ts | 14 ++ playground/typescript/.gitignore | 30 ++++ playground/typescript/README.md | 40 +++++ playground/typescript/env.d.ts | 1 + playground/typescript/index.html | 13 ++ playground/typescript/package.json | 26 +++ playground/typescript/public/favicon.ico | Bin 0 -> 4286 bytes playground/typescript/src/App.vue | 10 ++ playground/typescript/src/assets/logo.svg | 1 + playground/typescript/src/assets/main.css | 6 + playground/typescript/src/main.ts | 6 + playground/typescript/tsconfig.app.json | 14 ++ playground/typescript/tsconfig.json | 11 ++ playground/typescript/tsconfig.node.json | 19 +++ playground/typescript/vite.config.ts | 16 ++ playground/vitest-cypress/.gitignore | 30 ++++ playground/vitest-cypress/README.md | 51 ++++++ playground/vitest-cypress/cypress.config.js | 8 + .../vitest-cypress/cypress/e2e/example.cy.js | 8 + .../vitest-cypress/cypress/e2e/jsconfig.json | 8 + .../cypress/fixtures/example.json | 5 + .../cypress/support/commands.js | 25 +++ .../vitest-cypress/cypress/support/e2e.js | 20 +++ playground/vitest-cypress/index.html | 13 ++ playground/vitest-cypress/jsconfig.json | 8 + playground/vitest-cypress/package.json | 26 +++ playground/vitest-cypress/public/favicon.ico | Bin 0 -> 4286 bytes playground/vitest-cypress/src/App.vue | 9 ++ playground/vitest-cypress/src/assets/logo.svg | 1 + playground/vitest-cypress/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ playground/vitest-cypress/src/main.js | 6 + playground/vitest-cypress/vite.config.js | 16 ++ playground/vitest-cypress/vitest.config.js | 14 ++ playground/vitest-nightwatch/.gitignore | 33 ++++ .../vitest-nightwatch/.vscode/extensions.json | 3 + playground/vitest-nightwatch/README.md | 58 +++++++ playground/vitest-nightwatch/index.html | 13 ++ playground/vitest-nightwatch/jsconfig.json | 8 + .../vitest-nightwatch/nightwatch.conf.cjs | 153 ++++++++++++++++++ playground/vitest-nightwatch/package.json | 29 ++++ .../vitest-nightwatch/public/favicon.ico | Bin 0 -> 4286 bytes playground/vitest-nightwatch/src/App.vue | 9 ++ .../vitest-nightwatch/src/assets/logo.svg | 1 + .../vitest-nightwatch/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ playground/vitest-nightwatch/src/main.js | 6 + .../vitest-nightwatch/tests/e2e/example.js | 11 ++ playground/vitest-nightwatch/vite.config.js | 18 +++ playground/vitest-nightwatch/vitest.config.js | 14 ++ playground/vitest-playwright/.gitignore | 33 ++++ .../vitest-playwright/.vscode/extensions.json | 3 + playground/vitest-playwright/README.md | 54 +++++++ playground/vitest-playwright/e2e/vue.spec.js | 8 + playground/vitest-playwright/index.html | 13 ++ playground/vitest-playwright/jsconfig.json | 8 + playground/vitest-playwright/package.json | 24 +++ .../vitest-playwright/playwright.config.js | 110 +++++++++++++ .../vitest-playwright/public/favicon.ico | Bin 0 -> 4286 bytes playground/vitest-playwright/src/App.vue | 9 ++ .../vitest-playwright/src/assets/logo.svg | 1 + .../vitest-playwright/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ playground/vitest-playwright/src/main.js | 6 + playground/vitest-playwright/vite.config.js | 16 ++ playground/vitest-playwright/vitest.config.js | 14 ++ playground/vitest/.gitignore | 30 ++++ playground/vitest/README.md | 35 ++++ playground/vitest/index.html | 13 ++ playground/vitest/jsconfig.json | 8 + playground/vitest/package.json | 22 +++ playground/vitest/public/favicon.ico | Bin 0 -> 4286 bytes playground/vitest/src/App.vue | 9 ++ playground/vitest/src/assets/logo.svg | 1 + playground/vitest/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ playground/vitest/src/main.js | 6 + playground/vitest/vite.config.js | 16 ++ playground/vitest/vitest.config.js | 14 ++ playground/with-tests/.gitignore | 30 ++++ playground/with-tests/README.md | 51 ++++++ playground/with-tests/cypress.config.js | 8 + .../with-tests/cypress/e2e/example.cy.js | 8 + .../with-tests/cypress/e2e/jsconfig.json | 8 + .../with-tests/cypress/fixtures/example.json | 5 + .../with-tests/cypress/support/commands.js | 25 +++ playground/with-tests/cypress/support/e2e.js | 20 +++ playground/with-tests/index.html | 13 ++ playground/with-tests/jsconfig.json | 8 + playground/with-tests/package.json | 26 +++ playground/with-tests/public/favicon.ico | Bin 0 -> 4286 bytes playground/with-tests/src/App.vue | 9 ++ playground/with-tests/src/assets/logo.svg | 1 + playground/with-tests/src/assets/main.css | 6 + .../components/__tests__/HelloWorld.spec.js | 11 ++ playground/with-tests/src/main.js | 6 + playground/with-tests/vite.config.js | 16 ++ playground/with-tests/vitest.config.js | 14 ++ pnpm-lock.yaml | 13 ++ scripts/LICENSE | 33 ++++ template/base/.eslintignore | 5 + template/base/.eslintrc.cjs | 119 ++++++++++++++ template/base/.gitignore | 36 +++++ template/base/.prettierrc.json | 9 ++ template/base/package.json | 33 ++-- template/base/public/config.js | 23 +++ template/base/src/api/apiIndex.js | 13 ++ template/base/src/api/apisTest.js | 12 ++ template/base/src/config/configIndex.js | 21 +++ template/base/src/libs/custom_axios.js | 28 ++++ template/base/vite.config.js.ejs | 29 ++-- template/code/default/src/App.vue | 5 + template/code/router/src/App.vue | 2 +- template/code/typescript-router/src/App.vue | 80 +-------- .../typescript-router/src/router/index.ts | 11 +- .../code/typescript-router/src/views/Home.vue | 5 + utils/renderEslint.ts | 6 + 2506 files changed, 51083 insertions(+), 116 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/create-vue-customized.iml create mode 100644 .idea/markdown.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml delete mode 160000 playground create mode 100644 playground/pinia-cypress/.gitignore create mode 100644 playground/pinia-cypress/README.md create mode 100644 playground/pinia-cypress/cypress.config.js create mode 100644 playground/pinia-cypress/cypress/e2e/example.cy.js create mode 100644 playground/pinia-cypress/cypress/e2e/jsconfig.json create mode 100644 playground/pinia-cypress/cypress/fixtures/example.json create mode 100644 playground/pinia-cypress/cypress/support/commands.js create mode 100644 playground/pinia-cypress/cypress/support/component-index.html create mode 100644 playground/pinia-cypress/cypress/support/component.js create mode 100644 playground/pinia-cypress/cypress/support/e2e.js create mode 100644 playground/pinia-cypress/index.html create mode 100644 playground/pinia-cypress/jsconfig.json create mode 100644 playground/pinia-cypress/package.json create mode 100644 playground/pinia-cypress/public/favicon.ico create mode 100644 playground/pinia-cypress/src/App.vue create mode 100644 playground/pinia-cypress/src/assets/logo.svg create mode 100644 playground/pinia-cypress/src/assets/main.css create mode 100644 playground/pinia-cypress/src/components/__tests__/HelloWorld.cy.js create mode 100644 playground/pinia-cypress/src/main.js create mode 100644 playground/pinia-cypress/src/stores/counter.js create mode 100644 playground/pinia-cypress/vite.config.js create mode 100644 playground/pinia-nightwatch/.gitignore create mode 100644 playground/pinia-nightwatch/.vscode/extensions.json create mode 100644 playground/pinia-nightwatch/README.md create mode 100644 playground/pinia-nightwatch/index.html create mode 100644 playground/pinia-nightwatch/jsconfig.json create mode 100644 playground/pinia-nightwatch/nightwatch.conf.cjs create mode 100644 playground/pinia-nightwatch/nightwatch/index.html create mode 100644 playground/pinia-nightwatch/package.json create mode 100644 playground/pinia-nightwatch/public/favicon.ico create mode 100644 playground/pinia-nightwatch/src/App.vue create mode 100644 playground/pinia-nightwatch/src/assets/logo.svg create mode 100644 playground/pinia-nightwatch/src/assets/main.css create mode 100644 playground/pinia-nightwatch/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/pinia-nightwatch/src/main.js create mode 100644 playground/pinia-nightwatch/src/stores/counter.js create mode 100644 playground/pinia-nightwatch/tests/e2e/example.js create mode 100644 playground/pinia-nightwatch/vite.config.js create mode 100644 playground/pinia-playwright/.gitignore create mode 100644 playground/pinia-playwright/.vscode/extensions.json create mode 100644 playground/pinia-playwright/README.md create mode 100644 playground/pinia-playwright/e2e/vue.spec.js create mode 100644 playground/pinia-playwright/index.html create mode 100644 playground/pinia-playwright/jsconfig.json create mode 100644 playground/pinia-playwright/package.json create mode 100644 playground/pinia-playwright/playwright.config.js create mode 100644 playground/pinia-playwright/public/favicon.ico create mode 100644 playground/pinia-playwright/src/App.vue create mode 100644 playground/pinia-playwright/src/assets/logo.svg create mode 100644 playground/pinia-playwright/src/assets/main.css create mode 100644 playground/pinia-playwright/src/main.js create mode 100644 playground/pinia-playwright/src/stores/counter.js create mode 100644 playground/pinia-playwright/vite.config.js create mode 100644 playground/pinia-vitest-cypress/.gitignore create mode 100644 playground/pinia-vitest-cypress/README.md create mode 100644 playground/pinia-vitest-cypress/cypress.config.js create mode 100644 playground/pinia-vitest-cypress/cypress/e2e/example.cy.js create mode 100644 playground/pinia-vitest-cypress/cypress/e2e/jsconfig.json create mode 100644 playground/pinia-vitest-cypress/cypress/fixtures/example.json create mode 100644 playground/pinia-vitest-cypress/cypress/support/commands.js create mode 100644 playground/pinia-vitest-cypress/cypress/support/e2e.js create mode 100644 playground/pinia-vitest-cypress/index.html create mode 100644 playground/pinia-vitest-cypress/jsconfig.json create mode 100644 playground/pinia-vitest-cypress/package.json create mode 100644 playground/pinia-vitest-cypress/public/favicon.ico create mode 100644 playground/pinia-vitest-cypress/src/App.vue create mode 100644 playground/pinia-vitest-cypress/src/assets/logo.svg create mode 100644 playground/pinia-vitest-cypress/src/assets/main.css create mode 100644 playground/pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/pinia-vitest-cypress/src/main.js create mode 100644 playground/pinia-vitest-cypress/src/stores/counter.js create mode 100644 playground/pinia-vitest-cypress/vite.config.js create mode 100644 playground/pinia-vitest-cypress/vitest.config.js create mode 100644 playground/pinia-vitest-nightwatch/.gitignore create mode 100644 playground/pinia-vitest-nightwatch/.vscode/extensions.json create mode 100644 playground/pinia-vitest-nightwatch/README.md create mode 100644 playground/pinia-vitest-nightwatch/index.html create mode 100644 playground/pinia-vitest-nightwatch/jsconfig.json create mode 100644 playground/pinia-vitest-nightwatch/nightwatch.conf.cjs create mode 100644 playground/pinia-vitest-nightwatch/package.json create mode 100644 playground/pinia-vitest-nightwatch/public/favicon.ico create mode 100644 playground/pinia-vitest-nightwatch/src/App.vue create mode 100644 playground/pinia-vitest-nightwatch/src/assets/logo.svg create mode 100644 playground/pinia-vitest-nightwatch/src/assets/main.css create mode 100644 playground/pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/pinia-vitest-nightwatch/src/main.js create mode 100644 playground/pinia-vitest-nightwatch/src/stores/counter.js create mode 100644 playground/pinia-vitest-nightwatch/tests/e2e/example.js create mode 100644 playground/pinia-vitest-nightwatch/vite.config.js create mode 100644 playground/pinia-vitest-nightwatch/vitest.config.js create mode 100644 playground/pinia-vitest-playwright/.gitignore create mode 100644 playground/pinia-vitest-playwright/.vscode/extensions.json create mode 100644 playground/pinia-vitest-playwright/README.md create mode 100644 playground/pinia-vitest-playwright/e2e/vue.spec.js create mode 100644 playground/pinia-vitest-playwright/index.html create mode 100644 playground/pinia-vitest-playwright/jsconfig.json create mode 100644 playground/pinia-vitest-playwright/package.json create mode 100644 playground/pinia-vitest-playwright/playwright.config.js create mode 100644 playground/pinia-vitest-playwright/public/favicon.ico create mode 100644 playground/pinia-vitest-playwright/src/App.vue create mode 100644 playground/pinia-vitest-playwright/src/assets/logo.svg create mode 100644 playground/pinia-vitest-playwright/src/assets/main.css create mode 100644 playground/pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/pinia-vitest-playwright/src/main.js create mode 100644 playground/pinia-vitest-playwright/src/stores/counter.js create mode 100644 playground/pinia-vitest-playwright/vite.config.js create mode 100644 playground/pinia-vitest-playwright/vitest.config.js create mode 100644 playground/pinia-vitest/.gitignore create mode 100644 playground/pinia-vitest/README.md create mode 100644 playground/pinia-vitest/index.html create mode 100644 playground/pinia-vitest/jsconfig.json create mode 100644 playground/pinia-vitest/package.json create mode 100644 playground/pinia-vitest/public/favicon.ico create mode 100644 playground/pinia-vitest/src/App.vue create mode 100644 playground/pinia-vitest/src/assets/logo.svg create mode 100644 playground/pinia-vitest/src/assets/main.css create mode 100644 playground/pinia-vitest/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/pinia-vitest/src/main.js create mode 100644 playground/pinia-vitest/src/stores/counter.js create mode 100644 playground/pinia-vitest/vite.config.js create mode 100644 playground/pinia-vitest/vitest.config.js create mode 100644 playground/pinia-with-tests/.gitignore create mode 100644 playground/pinia-with-tests/README.md create mode 100644 playground/pinia-with-tests/cypress.config.js create mode 100644 playground/pinia-with-tests/cypress/e2e/example.cy.js create mode 100644 playground/pinia-with-tests/cypress/e2e/jsconfig.json create mode 100644 playground/pinia-with-tests/cypress/fixtures/example.json create mode 100644 playground/pinia-with-tests/cypress/support/commands.js create mode 100644 playground/pinia-with-tests/cypress/support/e2e.js create mode 100644 playground/pinia-with-tests/index.html create mode 100644 playground/pinia-with-tests/jsconfig.json create mode 100644 playground/pinia-with-tests/package.json create mode 100644 playground/pinia-with-tests/public/favicon.ico create mode 100644 playground/pinia-with-tests/src/App.vue create mode 100644 playground/pinia-with-tests/src/assets/logo.svg create mode 100644 playground/pinia-with-tests/src/assets/main.css create mode 100644 playground/pinia-with-tests/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/pinia-with-tests/src/main.js create mode 100644 playground/pinia-with-tests/src/stores/counter.js create mode 100644 playground/pinia-with-tests/vite.config.js create mode 100644 playground/pinia-with-tests/vitest.config.js create mode 100644 playground/pinia/.gitignore create mode 100644 playground/pinia/README.md create mode 100644 playground/pinia/index.html create mode 100644 playground/pinia/jsconfig.json create mode 100644 playground/pinia/package.json create mode 100644 playground/pinia/public/favicon.ico create mode 100644 playground/pinia/src/App.vue create mode 100644 playground/pinia/src/assets/logo.svg create mode 100644 playground/pinia/src/assets/main.css create mode 100644 playground/pinia/src/main.js create mode 100644 playground/pinia/src/stores/counter.js create mode 100644 playground/pinia/vite.config.js create mode 100644 playground/playwright/.gitignore create mode 100644 playground/playwright/.vscode/extensions.json create mode 100644 playground/playwright/README.md create mode 100644 playground/playwright/e2e/vue.spec.js create mode 100644 playground/playwright/index.html create mode 100644 playground/playwright/jsconfig.json create mode 100644 playground/playwright/package.json create mode 100644 playground/playwright/playwright.config.js create mode 100644 playground/playwright/public/favicon.ico create mode 100644 playground/playwright/src/App.vue create mode 100644 playground/playwright/src/assets/logo.svg create mode 100644 playground/playwright/src/assets/main.css create mode 100644 playground/playwright/src/main.js create mode 100644 playground/playwright/vite.config.js create mode 100644 playground/router-cypress/.gitignore create mode 100644 playground/router-cypress/README.md create mode 100644 playground/router-cypress/cypress.config.js create mode 100644 playground/router-cypress/cypress/e2e/example.cy.js create mode 100644 playground/router-cypress/cypress/e2e/jsconfig.json create mode 100644 playground/router-cypress/cypress/fixtures/example.json create mode 100644 playground/router-cypress/cypress/support/commands.js create mode 100644 playground/router-cypress/cypress/support/component-index.html create mode 100644 playground/router-cypress/cypress/support/component.js create mode 100644 playground/router-cypress/cypress/support/e2e.js create mode 100644 playground/router-cypress/index.html create mode 100644 playground/router-cypress/jsconfig.json create mode 100644 playground/router-cypress/package.json create mode 100644 playground/router-cypress/public/favicon.ico create mode 100644 playground/router-cypress/src/App.vue create mode 100644 playground/router-cypress/src/assets/logo.svg create mode 100644 playground/router-cypress/src/assets/main.css create mode 100644 playground/router-cypress/src/components/__tests__/HelloWorld.cy.js create mode 100644 playground/router-cypress/src/main.js create mode 100644 playground/router-cypress/src/router/index.js create mode 100644 playground/router-cypress/src/views/Home.vue create mode 100644 playground/router-cypress/vite.config.js create mode 100644 playground/router-nightwatch/.gitignore create mode 100644 playground/router-nightwatch/.vscode/extensions.json create mode 100644 playground/router-nightwatch/README.md create mode 100644 playground/router-nightwatch/index.html create mode 100644 playground/router-nightwatch/jsconfig.json create mode 100644 playground/router-nightwatch/nightwatch.conf.cjs create mode 100644 playground/router-nightwatch/nightwatch/index.html create mode 100644 playground/router-nightwatch/package.json create mode 100644 playground/router-nightwatch/public/favicon.ico create mode 100644 playground/router-nightwatch/src/App.vue create mode 100644 playground/router-nightwatch/src/assets/logo.svg create mode 100644 playground/router-nightwatch/src/assets/main.css create mode 100644 playground/router-nightwatch/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/router-nightwatch/src/main.js create mode 100644 playground/router-nightwatch/src/router/index.js create mode 100644 playground/router-nightwatch/src/views/Home.vue create mode 100644 playground/router-nightwatch/tests/e2e/example.js create mode 100644 playground/router-nightwatch/vite.config.js create mode 100644 playground/router-pinia-cypress/.gitignore create mode 100644 playground/router-pinia-cypress/README.md create mode 100644 playground/router-pinia-cypress/cypress.config.js create mode 100644 playground/router-pinia-cypress/cypress/e2e/example.cy.js create mode 100644 playground/router-pinia-cypress/cypress/e2e/jsconfig.json create mode 100644 playground/router-pinia-cypress/cypress/fixtures/example.json create mode 100644 playground/router-pinia-cypress/cypress/support/commands.js create mode 100644 playground/router-pinia-cypress/cypress/support/component-index.html create mode 100644 playground/router-pinia-cypress/cypress/support/component.js create mode 100644 playground/router-pinia-cypress/cypress/support/e2e.js create mode 100644 playground/router-pinia-cypress/index.html create mode 100644 playground/router-pinia-cypress/jsconfig.json create mode 100644 playground/router-pinia-cypress/package.json create mode 100644 playground/router-pinia-cypress/public/favicon.ico create mode 100644 playground/router-pinia-cypress/src/App.vue create mode 100644 playground/router-pinia-cypress/src/assets/logo.svg create mode 100644 playground/router-pinia-cypress/src/assets/main.css create mode 100644 playground/router-pinia-cypress/src/components/__tests__/HelloWorld.cy.js create mode 100644 playground/router-pinia-cypress/src/main.js create mode 100644 playground/router-pinia-cypress/src/router/index.js create mode 100644 playground/router-pinia-cypress/src/stores/counter.js create mode 100644 playground/router-pinia-cypress/src/views/Home.vue create mode 100644 playground/router-pinia-cypress/vite.config.js create mode 100644 playground/router-pinia-nightwatch/.gitignore create mode 100644 playground/router-pinia-nightwatch/.vscode/extensions.json create mode 100644 playground/router-pinia-nightwatch/README.md create mode 100644 playground/router-pinia-nightwatch/index.html create mode 100644 playground/router-pinia-nightwatch/jsconfig.json create mode 100644 playground/router-pinia-nightwatch/nightwatch.conf.cjs create mode 100644 playground/router-pinia-nightwatch/nightwatch/index.html create mode 100644 playground/router-pinia-nightwatch/package.json create mode 100644 playground/router-pinia-nightwatch/public/favicon.ico create mode 100644 playground/router-pinia-nightwatch/src/App.vue create mode 100644 playground/router-pinia-nightwatch/src/assets/logo.svg create mode 100644 playground/router-pinia-nightwatch/src/assets/main.css create mode 100644 playground/router-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/router-pinia-nightwatch/src/main.js create mode 100644 playground/router-pinia-nightwatch/src/router/index.js create mode 100644 playground/router-pinia-nightwatch/src/stores/counter.js create mode 100644 playground/router-pinia-nightwatch/src/views/Home.vue create mode 100644 playground/router-pinia-nightwatch/tests/e2e/example.js create mode 100644 playground/router-pinia-nightwatch/vite.config.js create mode 100644 playground/router-pinia-playwright/.gitignore create mode 100644 playground/router-pinia-playwright/.vscode/extensions.json create mode 100644 playground/router-pinia-playwright/README.md create mode 100644 playground/router-pinia-playwright/e2e/vue.spec.js create mode 100644 playground/router-pinia-playwright/index.html create mode 100644 playground/router-pinia-playwright/jsconfig.json create mode 100644 playground/router-pinia-playwright/package.json create mode 100644 playground/router-pinia-playwright/playwright.config.js create mode 100644 playground/router-pinia-playwright/public/favicon.ico create mode 100644 playground/router-pinia-playwright/src/App.vue create mode 100644 playground/router-pinia-playwright/src/assets/logo.svg create mode 100644 playground/router-pinia-playwright/src/assets/main.css create mode 100644 playground/router-pinia-playwright/src/main.js create mode 100644 playground/router-pinia-playwright/src/router/index.js create mode 100644 playground/router-pinia-playwright/src/stores/counter.js create mode 100644 playground/router-pinia-playwright/src/views/Home.vue create mode 100644 playground/router-pinia-playwright/vite.config.js create mode 100644 playground/router-pinia-vitest-cypress/.gitignore create mode 100644 playground/router-pinia-vitest-cypress/README.md create mode 100644 playground/router-pinia-vitest-cypress/cypress.config.js create mode 100644 playground/router-pinia-vitest-cypress/cypress/e2e/example.cy.js create mode 100644 playground/router-pinia-vitest-cypress/cypress/e2e/jsconfig.json create mode 100644 playground/router-pinia-vitest-cypress/cypress/fixtures/example.json create mode 100644 playground/router-pinia-vitest-cypress/cypress/support/commands.js create mode 100644 playground/router-pinia-vitest-cypress/cypress/support/e2e.js create mode 100644 playground/router-pinia-vitest-cypress/index.html create mode 100644 playground/router-pinia-vitest-cypress/jsconfig.json create mode 100644 playground/router-pinia-vitest-cypress/package.json create mode 100644 playground/router-pinia-vitest-cypress/public/favicon.ico create mode 100644 playground/router-pinia-vitest-cypress/src/App.vue create mode 100644 playground/router-pinia-vitest-cypress/src/assets/logo.svg create mode 100644 playground/router-pinia-vitest-cypress/src/assets/main.css create mode 100644 playground/router-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/router-pinia-vitest-cypress/src/main.js create mode 100644 playground/router-pinia-vitest-cypress/src/router/index.js create mode 100644 playground/router-pinia-vitest-cypress/src/stores/counter.js create mode 100644 playground/router-pinia-vitest-cypress/src/views/Home.vue create mode 100644 playground/router-pinia-vitest-cypress/vite.config.js create mode 100644 playground/router-pinia-vitest-cypress/vitest.config.js create mode 100644 playground/router-pinia-vitest-nightwatch/.gitignore create mode 100644 playground/router-pinia-vitest-nightwatch/.vscode/extensions.json create mode 100644 playground/router-pinia-vitest-nightwatch/README.md create mode 100644 playground/router-pinia-vitest-nightwatch/index.html create mode 100644 playground/router-pinia-vitest-nightwatch/jsconfig.json create mode 100644 playground/router-pinia-vitest-nightwatch/nightwatch.conf.cjs create mode 100644 playground/router-pinia-vitest-nightwatch/package.json create mode 100644 playground/router-pinia-vitest-nightwatch/public/favicon.ico create mode 100644 playground/router-pinia-vitest-nightwatch/src/App.vue create mode 100644 playground/router-pinia-vitest-nightwatch/src/assets/logo.svg create mode 100644 playground/router-pinia-vitest-nightwatch/src/assets/main.css create mode 100644 playground/router-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/router-pinia-vitest-nightwatch/src/main.js create mode 100644 playground/router-pinia-vitest-nightwatch/src/router/index.js create mode 100644 playground/router-pinia-vitest-nightwatch/src/stores/counter.js create mode 100644 playground/router-pinia-vitest-nightwatch/src/views/Home.vue create mode 100644 playground/router-pinia-vitest-nightwatch/tests/e2e/example.js create mode 100644 playground/router-pinia-vitest-nightwatch/vite.config.js create mode 100644 playground/router-pinia-vitest-nightwatch/vitest.config.js create mode 100644 playground/router-pinia-vitest-playwright/.gitignore create mode 100644 playground/router-pinia-vitest-playwright/.vscode/extensions.json create mode 100644 playground/router-pinia-vitest-playwright/README.md create mode 100644 playground/router-pinia-vitest-playwright/e2e/vue.spec.js create mode 100644 playground/router-pinia-vitest-playwright/index.html create mode 100644 playground/router-pinia-vitest-playwright/jsconfig.json create mode 100644 playground/router-pinia-vitest-playwright/package.json create mode 100644 playground/router-pinia-vitest-playwright/playwright.config.js create mode 100644 playground/router-pinia-vitest-playwright/public/favicon.ico create mode 100644 playground/router-pinia-vitest-playwright/src/App.vue create mode 100644 playground/router-pinia-vitest-playwright/src/assets/logo.svg create mode 100644 playground/router-pinia-vitest-playwright/src/assets/main.css create mode 100644 playground/router-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/router-pinia-vitest-playwright/src/main.js create mode 100644 playground/router-pinia-vitest-playwright/src/router/index.js create mode 100644 playground/router-pinia-vitest-playwright/src/stores/counter.js create mode 100644 playground/router-pinia-vitest-playwright/src/views/Home.vue create mode 100644 playground/router-pinia-vitest-playwright/vite.config.js create mode 100644 playground/router-pinia-vitest-playwright/vitest.config.js create mode 100644 playground/router-pinia-vitest/.gitignore create mode 100644 playground/router-pinia-vitest/README.md create mode 100644 playground/router-pinia-vitest/index.html create mode 100644 playground/router-pinia-vitest/jsconfig.json create mode 100644 playground/router-pinia-vitest/package.json create mode 100644 playground/router-pinia-vitest/public/favicon.ico create mode 100644 playground/router-pinia-vitest/src/App.vue create mode 100644 playground/router-pinia-vitest/src/assets/logo.svg create mode 100644 playground/router-pinia-vitest/src/assets/main.css create mode 100644 playground/router-pinia-vitest/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/router-pinia-vitest/src/main.js create mode 100644 playground/router-pinia-vitest/src/router/index.js create mode 100644 playground/router-pinia-vitest/src/stores/counter.js create mode 100644 playground/router-pinia-vitest/src/views/Home.vue create mode 100644 playground/router-pinia-vitest/vite.config.js create mode 100644 playground/router-pinia-vitest/vitest.config.js create mode 100644 playground/router-pinia-with-tests/.gitignore create mode 100644 playground/router-pinia-with-tests/README.md create mode 100644 playground/router-pinia-with-tests/cypress.config.js create mode 100644 playground/router-pinia-with-tests/cypress/e2e/example.cy.js create mode 100644 playground/router-pinia-with-tests/cypress/e2e/jsconfig.json create mode 100644 playground/router-pinia-with-tests/cypress/fixtures/example.json create mode 100644 playground/router-pinia-with-tests/cypress/support/commands.js create mode 100644 playground/router-pinia-with-tests/cypress/support/e2e.js create mode 100644 playground/router-pinia-with-tests/index.html create mode 100644 playground/router-pinia-with-tests/jsconfig.json create mode 100644 playground/router-pinia-with-tests/package.json create mode 100644 playground/router-pinia-with-tests/public/favicon.ico create mode 100644 playground/router-pinia-with-tests/src/App.vue create mode 100644 playground/router-pinia-with-tests/src/assets/logo.svg create mode 100644 playground/router-pinia-with-tests/src/assets/main.css create mode 100644 playground/router-pinia-with-tests/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/router-pinia-with-tests/src/main.js create mode 100644 playground/router-pinia-with-tests/src/router/index.js create mode 100644 playground/router-pinia-with-tests/src/stores/counter.js create mode 100644 playground/router-pinia-with-tests/src/views/Home.vue create mode 100644 playground/router-pinia-with-tests/vite.config.js create mode 100644 playground/router-pinia-with-tests/vitest.config.js create mode 100644 playground/router-pinia/.gitignore create mode 100644 playground/router-pinia/README.md create mode 100644 playground/router-pinia/index.html create mode 100644 playground/router-pinia/jsconfig.json create mode 100644 playground/router-pinia/package.json create mode 100644 playground/router-pinia/public/favicon.ico create mode 100644 playground/router-pinia/src/App.vue create mode 100644 playground/router-pinia/src/assets/logo.svg create mode 100644 playground/router-pinia/src/assets/main.css create mode 100644 playground/router-pinia/src/main.js create mode 100644 playground/router-pinia/src/router/index.js create mode 100644 playground/router-pinia/src/stores/counter.js create mode 100644 playground/router-pinia/src/views/Home.vue create mode 100644 playground/router-pinia/vite.config.js create mode 100644 playground/router-playwright/.gitignore create mode 100644 playground/router-playwright/.vscode/extensions.json create mode 100644 playground/router-playwright/README.md create mode 100644 playground/router-playwright/e2e/vue.spec.js create mode 100644 playground/router-playwright/index.html create mode 100644 playground/router-playwright/jsconfig.json create mode 100644 playground/router-playwright/package.json create mode 100644 playground/router-playwright/playwright.config.js create mode 100644 playground/router-playwright/public/favicon.ico create mode 100644 playground/router-playwright/src/App.vue create mode 100644 playground/router-playwright/src/assets/logo.svg create mode 100644 playground/router-playwright/src/assets/main.css create mode 100644 playground/router-playwright/src/main.js create mode 100644 playground/router-playwright/src/router/index.js create mode 100644 playground/router-playwright/src/views/Home.vue create mode 100644 playground/router-playwright/vite.config.js create mode 100644 playground/router-vitest-cypress/.gitignore create mode 100644 playground/router-vitest-cypress/README.md create mode 100644 playground/router-vitest-cypress/cypress.config.js create mode 100644 playground/router-vitest-cypress/cypress/e2e/example.cy.js create mode 100644 playground/router-vitest-cypress/cypress/e2e/jsconfig.json create mode 100644 playground/router-vitest-cypress/cypress/fixtures/example.json create mode 100644 playground/router-vitest-cypress/cypress/support/commands.js create mode 100644 playground/router-vitest-cypress/cypress/support/e2e.js create mode 100644 playground/router-vitest-cypress/index.html create mode 100644 playground/router-vitest-cypress/jsconfig.json create mode 100644 playground/router-vitest-cypress/package.json create mode 100644 playground/router-vitest-cypress/public/favicon.ico create mode 100644 playground/router-vitest-cypress/src/App.vue create mode 100644 playground/router-vitest-cypress/src/assets/logo.svg create mode 100644 playground/router-vitest-cypress/src/assets/main.css create mode 100644 playground/router-vitest-cypress/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/router-vitest-cypress/src/main.js create mode 100644 playground/router-vitest-cypress/src/router/index.js create mode 100644 playground/router-vitest-cypress/src/views/Home.vue create mode 100644 playground/router-vitest-cypress/vite.config.js create mode 100644 playground/router-vitest-cypress/vitest.config.js create mode 100644 playground/router-vitest-nightwatch/.gitignore create mode 100644 playground/router-vitest-nightwatch/.vscode/extensions.json create mode 100644 playground/router-vitest-nightwatch/README.md create mode 100644 playground/router-vitest-nightwatch/index.html create mode 100644 playground/router-vitest-nightwatch/jsconfig.json create mode 100644 playground/router-vitest-nightwatch/nightwatch.conf.cjs create mode 100644 playground/router-vitest-nightwatch/package.json create mode 100644 playground/router-vitest-nightwatch/public/favicon.ico create mode 100644 playground/router-vitest-nightwatch/src/App.vue create mode 100644 playground/router-vitest-nightwatch/src/assets/logo.svg create mode 100644 playground/router-vitest-nightwatch/src/assets/main.css create mode 100644 playground/router-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/router-vitest-nightwatch/src/main.js create mode 100644 playground/router-vitest-nightwatch/src/router/index.js create mode 100644 playground/router-vitest-nightwatch/src/views/Home.vue create mode 100644 playground/router-vitest-nightwatch/tests/e2e/example.js create mode 100644 playground/router-vitest-nightwatch/vite.config.js create mode 100644 playground/router-vitest-nightwatch/vitest.config.js create mode 100644 playground/router-vitest-playwright/.gitignore create mode 100644 playground/router-vitest-playwright/.vscode/extensions.json create mode 100644 playground/router-vitest-playwright/README.md create mode 100644 playground/router-vitest-playwright/e2e/vue.spec.js create mode 100644 playground/router-vitest-playwright/index.html create mode 100644 playground/router-vitest-playwright/jsconfig.json create mode 100644 playground/router-vitest-playwright/package.json create mode 100644 playground/router-vitest-playwright/playwright.config.js create mode 100644 playground/router-vitest-playwright/public/favicon.ico create mode 100644 playground/router-vitest-playwright/src/App.vue create mode 100644 playground/router-vitest-playwright/src/assets/logo.svg create mode 100644 playground/router-vitest-playwright/src/assets/main.css create mode 100644 playground/router-vitest-playwright/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/router-vitest-playwright/src/main.js create mode 100644 playground/router-vitest-playwright/src/router/index.js create mode 100644 playground/router-vitest-playwright/src/views/Home.vue create mode 100644 playground/router-vitest-playwright/vite.config.js create mode 100644 playground/router-vitest-playwright/vitest.config.js create mode 100644 playground/router-vitest/.gitignore create mode 100644 playground/router-vitest/README.md create mode 100644 playground/router-vitest/index.html create mode 100644 playground/router-vitest/jsconfig.json create mode 100644 playground/router-vitest/package.json create mode 100644 playground/router-vitest/public/favicon.ico create mode 100644 playground/router-vitest/src/App.vue create mode 100644 playground/router-vitest/src/assets/logo.svg create mode 100644 playground/router-vitest/src/assets/main.css create mode 100644 playground/router-vitest/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/router-vitest/src/main.js create mode 100644 playground/router-vitest/src/router/index.js create mode 100644 playground/router-vitest/src/views/Home.vue create mode 100644 playground/router-vitest/vite.config.js create mode 100644 playground/router-vitest/vitest.config.js create mode 100644 playground/router-with-tests/.gitignore create mode 100644 playground/router-with-tests/README.md create mode 100644 playground/router-with-tests/cypress.config.js create mode 100644 playground/router-with-tests/cypress/e2e/example.cy.js create mode 100644 playground/router-with-tests/cypress/e2e/jsconfig.json create mode 100644 playground/router-with-tests/cypress/fixtures/example.json create mode 100644 playground/router-with-tests/cypress/support/commands.js create mode 100644 playground/router-with-tests/cypress/support/e2e.js create mode 100644 playground/router-with-tests/index.html create mode 100644 playground/router-with-tests/jsconfig.json create mode 100644 playground/router-with-tests/package.json create mode 100644 playground/router-with-tests/public/favicon.ico create mode 100644 playground/router-with-tests/src/App.vue create mode 100644 playground/router-with-tests/src/assets/logo.svg create mode 100644 playground/router-with-tests/src/assets/main.css create mode 100644 playground/router-with-tests/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/router-with-tests/src/main.js create mode 100644 playground/router-with-tests/src/router/index.js create mode 100644 playground/router-with-tests/src/views/Home.vue create mode 100644 playground/router-with-tests/vite.config.js create mode 100644 playground/router-with-tests/vitest.config.js create mode 100644 playground/router/.gitignore create mode 100644 playground/router/README.md create mode 100644 playground/router/index.html create mode 100644 playground/router/jsconfig.json create mode 100644 playground/router/package.json create mode 100644 playground/router/public/favicon.ico create mode 100644 playground/router/src/App.vue create mode 100644 playground/router/src/assets/logo.svg create mode 100644 playground/router/src/assets/main.css create mode 100644 playground/router/src/main.js create mode 100644 playground/router/src/router/index.js create mode 100644 playground/router/src/views/Home.vue create mode 100644 playground/router/vite.config.js create mode 100644 playground/typescript-cypress/.gitignore create mode 100644 playground/typescript-cypress/README.md create mode 100644 playground/typescript-cypress/cypress.config.ts create mode 100644 playground/typescript-cypress/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-cypress/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-cypress/cypress/fixtures/example.json create mode 100644 playground/typescript-cypress/cypress/support/commands.ts create mode 100644 playground/typescript-cypress/cypress/support/component-index.html create mode 100644 playground/typescript-cypress/cypress/support/component.ts create mode 100644 playground/typescript-cypress/cypress/support/e2e.ts create mode 100644 playground/typescript-cypress/env.d.ts create mode 100644 playground/typescript-cypress/index.html create mode 100644 playground/typescript-cypress/package.json create mode 100644 playground/typescript-cypress/public/favicon.ico create mode 100644 playground/typescript-cypress/src/App.vue create mode 100644 playground/typescript-cypress/src/assets/logo.svg create mode 100644 playground/typescript-cypress/src/assets/main.css create mode 100644 playground/typescript-cypress/src/components/__tests__/HelloWorld.cy.ts create mode 100644 playground/typescript-cypress/src/main.ts create mode 100644 playground/typescript-cypress/tsconfig.app.json create mode 100644 playground/typescript-cypress/tsconfig.cypress-ct.json create mode 100644 playground/typescript-cypress/tsconfig.json create mode 100644 playground/typescript-cypress/tsconfig.node.json create mode 100644 playground/typescript-cypress/vite.config.ts create mode 100644 playground/typescript-jsx-cypress/.gitignore create mode 100644 playground/typescript-jsx-cypress/README.md create mode 100644 playground/typescript-jsx-cypress/cypress.config.ts create mode 100644 playground/typescript-jsx-cypress/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-jsx-cypress/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-cypress/cypress/fixtures/example.json create mode 100644 playground/typescript-jsx-cypress/cypress/support/commands.ts create mode 100644 playground/typescript-jsx-cypress/cypress/support/component-index.html create mode 100644 playground/typescript-jsx-cypress/cypress/support/component.ts create mode 100644 playground/typescript-jsx-cypress/cypress/support/e2e.ts create mode 100644 playground/typescript-jsx-cypress/env.d.ts create mode 100644 playground/typescript-jsx-cypress/index.html create mode 100644 playground/typescript-jsx-cypress/package.json create mode 100644 playground/typescript-jsx-cypress/public/favicon.ico create mode 100644 playground/typescript-jsx-cypress/src/App.vue create mode 100644 playground/typescript-jsx-cypress/src/assets/logo.svg create mode 100644 playground/typescript-jsx-cypress/src/assets/main.css create mode 100644 playground/typescript-jsx-cypress/src/components/__tests__/HelloWorld.cy.ts create mode 100644 playground/typescript-jsx-cypress/src/main.ts create mode 100644 playground/typescript-jsx-cypress/tsconfig.app.json create mode 100644 playground/typescript-jsx-cypress/tsconfig.cypress-ct.json create mode 100644 playground/typescript-jsx-cypress/tsconfig.json create mode 100644 playground/typescript-jsx-cypress/tsconfig.node.json create mode 100644 playground/typescript-jsx-cypress/vite.config.ts create mode 100644 playground/typescript-jsx-nightwatch/.gitignore create mode 100644 playground/typescript-jsx-nightwatch/.vscode/extensions.json create mode 100644 playground/typescript-jsx-nightwatch/README.md create mode 100644 playground/typescript-jsx-nightwatch/env.d.ts create mode 100644 playground/typescript-jsx-nightwatch/index.html create mode 100644 playground/typescript-jsx-nightwatch/nightwatch.conf.cjs create mode 100644 playground/typescript-jsx-nightwatch/nightwatch/index.html create mode 100644 playground/typescript-jsx-nightwatch/nightwatch/nightwatch.d.ts create mode 100644 playground/typescript-jsx-nightwatch/nightwatch/tsconfig.json create mode 100644 playground/typescript-jsx-nightwatch/package.json create mode 100644 playground/typescript-jsx-nightwatch/public/favicon.ico create mode 100644 playground/typescript-jsx-nightwatch/src/App.vue create mode 100644 playground/typescript-jsx-nightwatch/src/assets/logo.svg create mode 100644 playground/typescript-jsx-nightwatch/src/assets/main.css create mode 100644 playground/typescript-jsx-nightwatch/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-nightwatch/src/main.ts create mode 100644 playground/typescript-jsx-nightwatch/tests/e2e/example.ts create mode 100644 playground/typescript-jsx-nightwatch/tsconfig.app.json create mode 100644 playground/typescript-jsx-nightwatch/tsconfig.json create mode 100644 playground/typescript-jsx-nightwatch/tsconfig.node.json create mode 100644 playground/typescript-jsx-nightwatch/vite.config.ts create mode 100644 playground/typescript-jsx-pinia-cypress/.gitignore create mode 100644 playground/typescript-jsx-pinia-cypress/README.md create mode 100644 playground/typescript-jsx-pinia-cypress/cypress.config.ts create mode 100644 playground/typescript-jsx-pinia-cypress/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-jsx-pinia-cypress/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-pinia-cypress/cypress/fixtures/example.json create mode 100644 playground/typescript-jsx-pinia-cypress/cypress/support/commands.ts create mode 100644 playground/typescript-jsx-pinia-cypress/cypress/support/component-index.html create mode 100644 playground/typescript-jsx-pinia-cypress/cypress/support/component.ts create mode 100644 playground/typescript-jsx-pinia-cypress/cypress/support/e2e.ts create mode 100644 playground/typescript-jsx-pinia-cypress/env.d.ts create mode 100644 playground/typescript-jsx-pinia-cypress/index.html create mode 100644 playground/typescript-jsx-pinia-cypress/package.json create mode 100644 playground/typescript-jsx-pinia-cypress/public/favicon.ico create mode 100644 playground/typescript-jsx-pinia-cypress/src/App.vue create mode 100644 playground/typescript-jsx-pinia-cypress/src/assets/logo.svg create mode 100644 playground/typescript-jsx-pinia-cypress/src/assets/main.css create mode 100644 playground/typescript-jsx-pinia-cypress/src/components/__tests__/HelloWorld.cy.ts create mode 100644 playground/typescript-jsx-pinia-cypress/src/main.ts create mode 100644 playground/typescript-jsx-pinia-cypress/src/stores/counter.ts create mode 100644 playground/typescript-jsx-pinia-cypress/tsconfig.app.json create mode 100644 playground/typescript-jsx-pinia-cypress/tsconfig.cypress-ct.json create mode 100644 playground/typescript-jsx-pinia-cypress/tsconfig.json create mode 100644 playground/typescript-jsx-pinia-cypress/tsconfig.node.json create mode 100644 playground/typescript-jsx-pinia-cypress/vite.config.ts create mode 100644 playground/typescript-jsx-pinia-nightwatch/.gitignore create mode 100644 playground/typescript-jsx-pinia-nightwatch/.vscode/extensions.json create mode 100644 playground/typescript-jsx-pinia-nightwatch/README.md create mode 100644 playground/typescript-jsx-pinia-nightwatch/env.d.ts create mode 100644 playground/typescript-jsx-pinia-nightwatch/index.html create mode 100644 playground/typescript-jsx-pinia-nightwatch/nightwatch.conf.cjs create mode 100644 playground/typescript-jsx-pinia-nightwatch/nightwatch/index.html create mode 100644 playground/typescript-jsx-pinia-nightwatch/nightwatch/nightwatch.d.ts create mode 100644 playground/typescript-jsx-pinia-nightwatch/nightwatch/tsconfig.json create mode 100644 playground/typescript-jsx-pinia-nightwatch/package.json create mode 100644 playground/typescript-jsx-pinia-nightwatch/public/favicon.ico create mode 100644 playground/typescript-jsx-pinia-nightwatch/src/App.vue create mode 100644 playground/typescript-jsx-pinia-nightwatch/src/assets/logo.svg create mode 100644 playground/typescript-jsx-pinia-nightwatch/src/assets/main.css create mode 100644 playground/typescript-jsx-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-pinia-nightwatch/src/main.ts create mode 100644 playground/typescript-jsx-pinia-nightwatch/src/stores/counter.ts create mode 100644 playground/typescript-jsx-pinia-nightwatch/tests/e2e/example.ts create mode 100644 playground/typescript-jsx-pinia-nightwatch/tsconfig.app.json create mode 100644 playground/typescript-jsx-pinia-nightwatch/tsconfig.json create mode 100644 playground/typescript-jsx-pinia-nightwatch/tsconfig.node.json create mode 100644 playground/typescript-jsx-pinia-nightwatch/vite.config.ts create mode 100644 playground/typescript-jsx-pinia-playwright/.gitignore create mode 100644 playground/typescript-jsx-pinia-playwright/.vscode/extensions.json create mode 100644 playground/typescript-jsx-pinia-playwright/README.md create mode 100644 playground/typescript-jsx-pinia-playwright/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-pinia-playwright/e2e/vue.spec.ts create mode 100644 playground/typescript-jsx-pinia-playwright/env.d.ts create mode 100644 playground/typescript-jsx-pinia-playwright/index.html create mode 100644 playground/typescript-jsx-pinia-playwright/package.json create mode 100644 playground/typescript-jsx-pinia-playwright/playwright.config.ts create mode 100644 playground/typescript-jsx-pinia-playwright/public/favicon.ico create mode 100644 playground/typescript-jsx-pinia-playwright/src/App.vue create mode 100644 playground/typescript-jsx-pinia-playwright/src/assets/logo.svg create mode 100644 playground/typescript-jsx-pinia-playwright/src/assets/main.css create mode 100644 playground/typescript-jsx-pinia-playwright/src/main.ts create mode 100644 playground/typescript-jsx-pinia-playwright/src/stores/counter.ts create mode 100644 playground/typescript-jsx-pinia-playwright/tsconfig.app.json create mode 100644 playground/typescript-jsx-pinia-playwright/tsconfig.json create mode 100644 playground/typescript-jsx-pinia-playwright/tsconfig.node.json create mode 100644 playground/typescript-jsx-pinia-playwright/vite.config.ts create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/.gitignore create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/README.md create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/cypress.config.ts create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/cypress/fixtures/example.json create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/cypress/support/commands.ts create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/cypress/support/e2e.ts create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/env.d.ts create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/index.html create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/package.json create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/public/favicon.ico create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/src/App.vue create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/src/assets/logo.svg create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/src/assets/main.css create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/src/main.ts create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/src/stores/counter.ts create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/tsconfig.app.json create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/tsconfig.json create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/tsconfig.node.json create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/vite.config.ts create mode 100644 playground/typescript-jsx-pinia-vitest-cypress/vitest.config.ts create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/.gitignore create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/.vscode/extensions.json create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/README.md create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/env.d.ts create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/index.html create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/nightwatch.conf.cjs create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/nightwatch/nightwatch.d.ts create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/nightwatch/tsconfig.json create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/package.json create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/public/favicon.ico create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/src/App.vue create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/src/assets/logo.svg create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/src/assets/main.css create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/src/main.ts create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/src/stores/counter.ts create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/tests/e2e/example.ts create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/tsconfig.app.json create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/tsconfig.json create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/tsconfig.node.json create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/vite.config.ts create mode 100644 playground/typescript-jsx-pinia-vitest-nightwatch/vitest.config.ts create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/.gitignore create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/.vscode/extensions.json create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/README.md create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/e2e/vue.spec.ts create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/env.d.ts create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/index.html create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/package.json create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/playwright.config.ts create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/public/favicon.ico create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/src/App.vue create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/src/assets/logo.svg create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/src/assets/main.css create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/src/main.ts create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/src/stores/counter.ts create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/tsconfig.app.json create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/tsconfig.json create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/tsconfig.node.json create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/vite.config.ts create mode 100644 playground/typescript-jsx-pinia-vitest-playwright/vitest.config.ts create mode 100644 playground/typescript-jsx-pinia-vitest/.gitignore create mode 100644 playground/typescript-jsx-pinia-vitest/README.md create mode 100644 playground/typescript-jsx-pinia-vitest/env.d.ts create mode 100644 playground/typescript-jsx-pinia-vitest/index.html create mode 100644 playground/typescript-jsx-pinia-vitest/package.json create mode 100644 playground/typescript-jsx-pinia-vitest/public/favicon.ico create mode 100644 playground/typescript-jsx-pinia-vitest/src/App.vue create mode 100644 playground/typescript-jsx-pinia-vitest/src/assets/logo.svg create mode 100644 playground/typescript-jsx-pinia-vitest/src/assets/main.css create mode 100644 playground/typescript-jsx-pinia-vitest/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-pinia-vitest/src/main.ts create mode 100644 playground/typescript-jsx-pinia-vitest/src/stores/counter.ts create mode 100644 playground/typescript-jsx-pinia-vitest/tsconfig.app.json create mode 100644 playground/typescript-jsx-pinia-vitest/tsconfig.json create mode 100644 playground/typescript-jsx-pinia-vitest/tsconfig.node.json create mode 100644 playground/typescript-jsx-pinia-vitest/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-pinia-vitest/vite.config.ts create mode 100644 playground/typescript-jsx-pinia-vitest/vitest.config.ts create mode 100644 playground/typescript-jsx-pinia-with-tests/.gitignore create mode 100644 playground/typescript-jsx-pinia-with-tests/README.md create mode 100644 playground/typescript-jsx-pinia-with-tests/cypress.config.ts create mode 100644 playground/typescript-jsx-pinia-with-tests/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-jsx-pinia-with-tests/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-pinia-with-tests/cypress/fixtures/example.json create mode 100644 playground/typescript-jsx-pinia-with-tests/cypress/support/commands.ts create mode 100644 playground/typescript-jsx-pinia-with-tests/cypress/support/e2e.ts create mode 100644 playground/typescript-jsx-pinia-with-tests/env.d.ts create mode 100644 playground/typescript-jsx-pinia-with-tests/index.html create mode 100644 playground/typescript-jsx-pinia-with-tests/package.json create mode 100644 playground/typescript-jsx-pinia-with-tests/public/favicon.ico create mode 100644 playground/typescript-jsx-pinia-with-tests/src/App.vue create mode 100644 playground/typescript-jsx-pinia-with-tests/src/assets/logo.svg create mode 100644 playground/typescript-jsx-pinia-with-tests/src/assets/main.css create mode 100644 playground/typescript-jsx-pinia-with-tests/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-pinia-with-tests/src/main.ts create mode 100644 playground/typescript-jsx-pinia-with-tests/src/stores/counter.ts create mode 100644 playground/typescript-jsx-pinia-with-tests/tsconfig.app.json create mode 100644 playground/typescript-jsx-pinia-with-tests/tsconfig.json create mode 100644 playground/typescript-jsx-pinia-with-tests/tsconfig.node.json create mode 100644 playground/typescript-jsx-pinia-with-tests/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-pinia-with-tests/vite.config.ts create mode 100644 playground/typescript-jsx-pinia-with-tests/vitest.config.ts create mode 100644 playground/typescript-jsx-pinia/.gitignore create mode 100644 playground/typescript-jsx-pinia/README.md create mode 100644 playground/typescript-jsx-pinia/env.d.ts create mode 100644 playground/typescript-jsx-pinia/index.html create mode 100644 playground/typescript-jsx-pinia/package.json create mode 100644 playground/typescript-jsx-pinia/public/favicon.ico create mode 100644 playground/typescript-jsx-pinia/src/App.vue create mode 100644 playground/typescript-jsx-pinia/src/assets/logo.svg create mode 100644 playground/typescript-jsx-pinia/src/assets/main.css create mode 100644 playground/typescript-jsx-pinia/src/main.ts create mode 100644 playground/typescript-jsx-pinia/src/stores/counter.ts create mode 100644 playground/typescript-jsx-pinia/tsconfig.app.json create mode 100644 playground/typescript-jsx-pinia/tsconfig.json create mode 100644 playground/typescript-jsx-pinia/tsconfig.node.json create mode 100644 playground/typescript-jsx-pinia/vite.config.ts create mode 100644 playground/typescript-jsx-playwright/.gitignore create mode 100644 playground/typescript-jsx-playwright/.vscode/extensions.json create mode 100644 playground/typescript-jsx-playwright/README.md create mode 100644 playground/typescript-jsx-playwright/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-playwright/e2e/vue.spec.ts create mode 100644 playground/typescript-jsx-playwright/env.d.ts create mode 100644 playground/typescript-jsx-playwright/index.html create mode 100644 playground/typescript-jsx-playwright/package.json create mode 100644 playground/typescript-jsx-playwright/playwright.config.ts create mode 100644 playground/typescript-jsx-playwright/public/favicon.ico create mode 100644 playground/typescript-jsx-playwright/src/App.vue create mode 100644 playground/typescript-jsx-playwright/src/assets/logo.svg create mode 100644 playground/typescript-jsx-playwright/src/assets/main.css create mode 100644 playground/typescript-jsx-playwright/src/main.ts create mode 100644 playground/typescript-jsx-playwright/tsconfig.app.json create mode 100644 playground/typescript-jsx-playwright/tsconfig.json create mode 100644 playground/typescript-jsx-playwright/tsconfig.node.json create mode 100644 playground/typescript-jsx-playwright/vite.config.ts create mode 100644 playground/typescript-jsx-router-cypress/.gitignore create mode 100644 playground/typescript-jsx-router-cypress/README.md create mode 100644 playground/typescript-jsx-router-cypress/cypress.config.ts create mode 100644 playground/typescript-jsx-router-cypress/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-jsx-router-cypress/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-router-cypress/cypress/fixtures/example.json create mode 100644 playground/typescript-jsx-router-cypress/cypress/support/commands.ts create mode 100644 playground/typescript-jsx-router-cypress/cypress/support/component-index.html create mode 100644 playground/typescript-jsx-router-cypress/cypress/support/component.ts create mode 100644 playground/typescript-jsx-router-cypress/cypress/support/e2e.ts create mode 100644 playground/typescript-jsx-router-cypress/env.d.ts create mode 100644 playground/typescript-jsx-router-cypress/index.html create mode 100644 playground/typescript-jsx-router-cypress/package.json create mode 100644 playground/typescript-jsx-router-cypress/public/favicon.ico create mode 100644 playground/typescript-jsx-router-cypress/src/App.vue create mode 100644 playground/typescript-jsx-router-cypress/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router-cypress/src/assets/main.css create mode 100644 playground/typescript-jsx-router-cypress/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router-cypress/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router-cypress/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router-cypress/src/components/__tests__/HelloWorld.cy.ts create mode 100644 playground/typescript-jsx-router-cypress/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router-cypress/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router-cypress/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router-cypress/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router-cypress/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router-cypress/src/main.ts create mode 100644 playground/typescript-jsx-router-cypress/src/router/index.ts create mode 100644 playground/typescript-jsx-router-cypress/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router-cypress/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router-cypress/tsconfig.app.json create mode 100644 playground/typescript-jsx-router-cypress/tsconfig.cypress-ct.json create mode 100644 playground/typescript-jsx-router-cypress/tsconfig.json create mode 100644 playground/typescript-jsx-router-cypress/tsconfig.node.json create mode 100644 playground/typescript-jsx-router-cypress/vite.config.ts create mode 100644 playground/typescript-jsx-router-nightwatch/.gitignore create mode 100644 playground/typescript-jsx-router-nightwatch/.vscode/extensions.json create mode 100644 playground/typescript-jsx-router-nightwatch/README.md create mode 100644 playground/typescript-jsx-router-nightwatch/env.d.ts create mode 100644 playground/typescript-jsx-router-nightwatch/index.html create mode 100644 playground/typescript-jsx-router-nightwatch/nightwatch.conf.cjs create mode 100644 playground/typescript-jsx-router-nightwatch/nightwatch/index.html create mode 100644 playground/typescript-jsx-router-nightwatch/nightwatch/nightwatch.d.ts create mode 100644 playground/typescript-jsx-router-nightwatch/nightwatch/tsconfig.json create mode 100644 playground/typescript-jsx-router-nightwatch/package.json create mode 100644 playground/typescript-jsx-router-nightwatch/public/favicon.ico create mode 100644 playground/typescript-jsx-router-nightwatch/src/App.vue create mode 100644 playground/typescript-jsx-router-nightwatch/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router-nightwatch/src/assets/main.css create mode 100644 playground/typescript-jsx-router-nightwatch/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router-nightwatch/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router-nightwatch/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router-nightwatch/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-router-nightwatch/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router-nightwatch/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router-nightwatch/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router-nightwatch/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router-nightwatch/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router-nightwatch/src/main.ts create mode 100644 playground/typescript-jsx-router-nightwatch/src/router/index.ts create mode 100644 playground/typescript-jsx-router-nightwatch/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router-nightwatch/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router-nightwatch/tests/e2e/example.ts create mode 100644 playground/typescript-jsx-router-nightwatch/tsconfig.app.json create mode 100644 playground/typescript-jsx-router-nightwatch/tsconfig.json create mode 100644 playground/typescript-jsx-router-nightwatch/tsconfig.node.json create mode 100644 playground/typescript-jsx-router-nightwatch/vite.config.ts create mode 100644 playground/typescript-jsx-router-pinia-cypress/.gitignore create mode 100644 playground/typescript-jsx-router-pinia-cypress/README.md create mode 100644 playground/typescript-jsx-router-pinia-cypress/cypress.config.ts create mode 100644 playground/typescript-jsx-router-pinia-cypress/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-jsx-router-pinia-cypress/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-router-pinia-cypress/cypress/fixtures/example.json create mode 100644 playground/typescript-jsx-router-pinia-cypress/cypress/support/commands.ts create mode 100644 playground/typescript-jsx-router-pinia-cypress/cypress/support/component-index.html create mode 100644 playground/typescript-jsx-router-pinia-cypress/cypress/support/component.ts create mode 100644 playground/typescript-jsx-router-pinia-cypress/cypress/support/e2e.ts create mode 100644 playground/typescript-jsx-router-pinia-cypress/env.d.ts create mode 100644 playground/typescript-jsx-router-pinia-cypress/index.html create mode 100644 playground/typescript-jsx-router-pinia-cypress/package.json create mode 100644 playground/typescript-jsx-router-pinia-cypress/public/favicon.ico create mode 100644 playground/typescript-jsx-router-pinia-cypress/src/App.vue create mode 100644 playground/typescript-jsx-router-pinia-cypress/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router-pinia-cypress/src/assets/main.css create mode 100644 playground/typescript-jsx-router-pinia-cypress/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router-pinia-cypress/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router-pinia-cypress/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router-pinia-cypress/src/components/__tests__/HelloWorld.cy.ts create mode 100644 playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router-pinia-cypress/src/main.ts create mode 100644 playground/typescript-jsx-router-pinia-cypress/src/router/index.ts create mode 100644 playground/typescript-jsx-router-pinia-cypress/src/stores/counter.ts create mode 100644 playground/typescript-jsx-router-pinia-cypress/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router-pinia-cypress/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router-pinia-cypress/tsconfig.app.json create mode 100644 playground/typescript-jsx-router-pinia-cypress/tsconfig.cypress-ct.json create mode 100644 playground/typescript-jsx-router-pinia-cypress/tsconfig.json create mode 100644 playground/typescript-jsx-router-pinia-cypress/tsconfig.node.json create mode 100644 playground/typescript-jsx-router-pinia-cypress/vite.config.ts create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/.gitignore create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/.vscode/extensions.json create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/README.md create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/env.d.ts create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/index.html create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/nightwatch.conf.cjs create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/nightwatch/index.html create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/nightwatch/nightwatch.d.ts create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/nightwatch/tsconfig.json create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/package.json create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/public/favicon.ico create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/src/App.vue create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/src/assets/main.css create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/src/main.ts create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/src/router/index.ts create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/src/stores/counter.ts create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/tests/e2e/example.ts create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/tsconfig.app.json create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/tsconfig.json create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/tsconfig.node.json create mode 100644 playground/typescript-jsx-router-pinia-nightwatch/vite.config.ts create mode 100644 playground/typescript-jsx-router-pinia-playwright/.gitignore create mode 100644 playground/typescript-jsx-router-pinia-playwright/.vscode/extensions.json create mode 100644 playground/typescript-jsx-router-pinia-playwright/README.md create mode 100644 playground/typescript-jsx-router-pinia-playwright/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-router-pinia-playwright/e2e/vue.spec.ts create mode 100644 playground/typescript-jsx-router-pinia-playwright/env.d.ts create mode 100644 playground/typescript-jsx-router-pinia-playwright/index.html create mode 100644 playground/typescript-jsx-router-pinia-playwright/package.json create mode 100644 playground/typescript-jsx-router-pinia-playwright/playwright.config.ts create mode 100644 playground/typescript-jsx-router-pinia-playwright/public/favicon.ico create mode 100644 playground/typescript-jsx-router-pinia-playwright/src/App.vue create mode 100644 playground/typescript-jsx-router-pinia-playwright/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router-pinia-playwright/src/assets/main.css create mode 100644 playground/typescript-jsx-router-pinia-playwright/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router-pinia-playwright/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router-pinia-playwright/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router-pinia-playwright/src/main.ts create mode 100644 playground/typescript-jsx-router-pinia-playwright/src/router/index.ts create mode 100644 playground/typescript-jsx-router-pinia-playwright/src/stores/counter.ts create mode 100644 playground/typescript-jsx-router-pinia-playwright/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router-pinia-playwright/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router-pinia-playwright/tsconfig.app.json create mode 100644 playground/typescript-jsx-router-pinia-playwright/tsconfig.json create mode 100644 playground/typescript-jsx-router-pinia-playwright/tsconfig.node.json create mode 100644 playground/typescript-jsx-router-pinia-playwright/vite.config.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/.gitignore create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/README.md create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/cypress.config.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/cypress/fixtures/example.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/cypress/support/commands.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/cypress/support/e2e.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/env.d.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/index.html create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/package.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/public/favicon.ico create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/src/App.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/src/assets/main.css create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/src/main.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/src/router/index.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/src/stores/counter.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/tsconfig.app.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/tsconfig.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/tsconfig.node.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/vite.config.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-cypress/vitest.config.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/.gitignore create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/.vscode/extensions.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/README.md create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/env.d.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/index.html create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/nightwatch.conf.cjs create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/nightwatch/nightwatch.d.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/nightwatch/tsconfig.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/package.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/public/favicon.ico create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/src/App.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/src/assets/main.css create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/src/main.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/src/router/index.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/src/stores/counter.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/tests/e2e/example.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/tsconfig.app.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/tsconfig.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/tsconfig.node.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/vite.config.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-nightwatch/vitest.config.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/.gitignore create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/.vscode/extensions.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/README.md create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/e2e/vue.spec.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/env.d.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/index.html create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/package.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/playwright.config.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/public/favicon.ico create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/src/App.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/src/assets/main.css create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/src/main.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/src/router/index.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/src/stores/counter.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/tsconfig.app.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/tsconfig.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/tsconfig.node.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/vite.config.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest-playwright/vitest.config.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest/.gitignore create mode 100644 playground/typescript-jsx-router-pinia-vitest/README.md create mode 100644 playground/typescript-jsx-router-pinia-vitest/env.d.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest/index.html create mode 100644 playground/typescript-jsx-router-pinia-vitest/package.json create mode 100644 playground/typescript-jsx-router-pinia-vitest/public/favicon.ico create mode 100644 playground/typescript-jsx-router-pinia-vitest/src/App.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router-pinia-vitest/src/assets/main.css create mode 100644 playground/typescript-jsx-router-pinia-vitest/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest/src/main.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest/src/router/index.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest/src/stores/counter.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router-pinia-vitest/tsconfig.app.json create mode 100644 playground/typescript-jsx-router-pinia-vitest/tsconfig.json create mode 100644 playground/typescript-jsx-router-pinia-vitest/tsconfig.node.json create mode 100644 playground/typescript-jsx-router-pinia-vitest/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-router-pinia-vitest/vite.config.ts create mode 100644 playground/typescript-jsx-router-pinia-vitest/vitest.config.ts create mode 100644 playground/typescript-jsx-router-pinia-with-tests/.gitignore create mode 100644 playground/typescript-jsx-router-pinia-with-tests/README.md create mode 100644 playground/typescript-jsx-router-pinia-with-tests/cypress.config.ts create mode 100644 playground/typescript-jsx-router-pinia-with-tests/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-jsx-router-pinia-with-tests/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-router-pinia-with-tests/cypress/fixtures/example.json create mode 100644 playground/typescript-jsx-router-pinia-with-tests/cypress/support/commands.ts create mode 100644 playground/typescript-jsx-router-pinia-with-tests/cypress/support/e2e.ts create mode 100644 playground/typescript-jsx-router-pinia-with-tests/env.d.ts create mode 100644 playground/typescript-jsx-router-pinia-with-tests/index.html create mode 100644 playground/typescript-jsx-router-pinia-with-tests/package.json create mode 100644 playground/typescript-jsx-router-pinia-with-tests/public/favicon.ico create mode 100644 playground/typescript-jsx-router-pinia-with-tests/src/App.vue create mode 100644 playground/typescript-jsx-router-pinia-with-tests/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router-pinia-with-tests/src/assets/main.css create mode 100644 playground/typescript-jsx-router-pinia-with-tests/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router-pinia-with-tests/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router-pinia-with-tests/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router-pinia-with-tests/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router-pinia-with-tests/src/main.ts create mode 100644 playground/typescript-jsx-router-pinia-with-tests/src/router/index.ts create mode 100644 playground/typescript-jsx-router-pinia-with-tests/src/stores/counter.ts create mode 100644 playground/typescript-jsx-router-pinia-with-tests/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router-pinia-with-tests/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router-pinia-with-tests/tsconfig.app.json create mode 100644 playground/typescript-jsx-router-pinia-with-tests/tsconfig.json create mode 100644 playground/typescript-jsx-router-pinia-with-tests/tsconfig.node.json create mode 100644 playground/typescript-jsx-router-pinia-with-tests/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-router-pinia-with-tests/vite.config.ts create mode 100644 playground/typescript-jsx-router-pinia-with-tests/vitest.config.ts create mode 100644 playground/typescript-jsx-router-pinia/.gitignore create mode 100644 playground/typescript-jsx-router-pinia/README.md create mode 100644 playground/typescript-jsx-router-pinia/env.d.ts create mode 100644 playground/typescript-jsx-router-pinia/index.html create mode 100644 playground/typescript-jsx-router-pinia/package.json create mode 100644 playground/typescript-jsx-router-pinia/public/favicon.ico create mode 100644 playground/typescript-jsx-router-pinia/src/App.vue create mode 100644 playground/typescript-jsx-router-pinia/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router-pinia/src/assets/main.css create mode 100644 playground/typescript-jsx-router-pinia/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router-pinia/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router-pinia/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router-pinia/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router-pinia/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router-pinia/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router-pinia/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router-pinia/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router-pinia/src/main.ts create mode 100644 playground/typescript-jsx-router-pinia/src/router/index.ts create mode 100644 playground/typescript-jsx-router-pinia/src/stores/counter.ts create mode 100644 playground/typescript-jsx-router-pinia/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router-pinia/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router-pinia/tsconfig.app.json create mode 100644 playground/typescript-jsx-router-pinia/tsconfig.json create mode 100644 playground/typescript-jsx-router-pinia/tsconfig.node.json create mode 100644 playground/typescript-jsx-router-pinia/vite.config.ts create mode 100644 playground/typescript-jsx-router-playwright/.gitignore create mode 100644 playground/typescript-jsx-router-playwright/.vscode/extensions.json create mode 100644 playground/typescript-jsx-router-playwright/README.md create mode 100644 playground/typescript-jsx-router-playwright/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-router-playwright/e2e/vue.spec.ts create mode 100644 playground/typescript-jsx-router-playwright/env.d.ts create mode 100644 playground/typescript-jsx-router-playwright/index.html create mode 100644 playground/typescript-jsx-router-playwright/package.json create mode 100644 playground/typescript-jsx-router-playwright/playwright.config.ts create mode 100644 playground/typescript-jsx-router-playwright/public/favicon.ico create mode 100644 playground/typescript-jsx-router-playwright/src/App.vue create mode 100644 playground/typescript-jsx-router-playwright/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router-playwright/src/assets/main.css create mode 100644 playground/typescript-jsx-router-playwright/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router-playwright/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router-playwright/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router-playwright/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router-playwright/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router-playwright/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router-playwright/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router-playwright/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router-playwright/src/main.ts create mode 100644 playground/typescript-jsx-router-playwright/src/router/index.ts create mode 100644 playground/typescript-jsx-router-playwright/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router-playwright/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router-playwright/tsconfig.app.json create mode 100644 playground/typescript-jsx-router-playwright/tsconfig.json create mode 100644 playground/typescript-jsx-router-playwright/tsconfig.node.json create mode 100644 playground/typescript-jsx-router-playwright/vite.config.ts create mode 100644 playground/typescript-jsx-router-vitest-cypress/.gitignore create mode 100644 playground/typescript-jsx-router-vitest-cypress/README.md create mode 100644 playground/typescript-jsx-router-vitest-cypress/cypress.config.ts create mode 100644 playground/typescript-jsx-router-vitest-cypress/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-jsx-router-vitest-cypress/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-router-vitest-cypress/cypress/fixtures/example.json create mode 100644 playground/typescript-jsx-router-vitest-cypress/cypress/support/commands.ts create mode 100644 playground/typescript-jsx-router-vitest-cypress/cypress/support/e2e.ts create mode 100644 playground/typescript-jsx-router-vitest-cypress/env.d.ts create mode 100644 playground/typescript-jsx-router-vitest-cypress/index.html create mode 100644 playground/typescript-jsx-router-vitest-cypress/package.json create mode 100644 playground/typescript-jsx-router-vitest-cypress/public/favicon.ico create mode 100644 playground/typescript-jsx-router-vitest-cypress/src/App.vue create mode 100644 playground/typescript-jsx-router-vitest-cypress/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router-vitest-cypress/src/assets/main.css create mode 100644 playground/typescript-jsx-router-vitest-cypress/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router-vitest-cypress/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router-vitest-cypress/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router-vitest-cypress/src/main.ts create mode 100644 playground/typescript-jsx-router-vitest-cypress/src/router/index.ts create mode 100644 playground/typescript-jsx-router-vitest-cypress/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router-vitest-cypress/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router-vitest-cypress/tsconfig.app.json create mode 100644 playground/typescript-jsx-router-vitest-cypress/tsconfig.json create mode 100644 playground/typescript-jsx-router-vitest-cypress/tsconfig.node.json create mode 100644 playground/typescript-jsx-router-vitest-cypress/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-router-vitest-cypress/vite.config.ts create mode 100644 playground/typescript-jsx-router-vitest-cypress/vitest.config.ts create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/.gitignore create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/.vscode/extensions.json create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/README.md create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/env.d.ts create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/index.html create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/nightwatch.conf.cjs create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/nightwatch/nightwatch.d.ts create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/nightwatch/tsconfig.json create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/package.json create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/public/favicon.ico create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/src/App.vue create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/src/assets/main.css create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/src/main.ts create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/src/router/index.ts create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/tests/e2e/example.ts create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/tsconfig.app.json create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/tsconfig.json create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/tsconfig.node.json create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/vite.config.ts create mode 100644 playground/typescript-jsx-router-vitest-nightwatch/vitest.config.ts create mode 100644 playground/typescript-jsx-router-vitest-playwright/.gitignore create mode 100644 playground/typescript-jsx-router-vitest-playwright/.vscode/extensions.json create mode 100644 playground/typescript-jsx-router-vitest-playwright/README.md create mode 100644 playground/typescript-jsx-router-vitest-playwright/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-router-vitest-playwright/e2e/vue.spec.ts create mode 100644 playground/typescript-jsx-router-vitest-playwright/env.d.ts create mode 100644 playground/typescript-jsx-router-vitest-playwright/index.html create mode 100644 playground/typescript-jsx-router-vitest-playwright/package.json create mode 100644 playground/typescript-jsx-router-vitest-playwright/playwright.config.ts create mode 100644 playground/typescript-jsx-router-vitest-playwright/public/favicon.ico create mode 100644 playground/typescript-jsx-router-vitest-playwright/src/App.vue create mode 100644 playground/typescript-jsx-router-vitest-playwright/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router-vitest-playwright/src/assets/main.css create mode 100644 playground/typescript-jsx-router-vitest-playwright/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router-vitest-playwright/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router-vitest-playwright/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router-vitest-playwright/src/main.ts create mode 100644 playground/typescript-jsx-router-vitest-playwright/src/router/index.ts create mode 100644 playground/typescript-jsx-router-vitest-playwright/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router-vitest-playwright/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router-vitest-playwright/tsconfig.app.json create mode 100644 playground/typescript-jsx-router-vitest-playwright/tsconfig.json create mode 100644 playground/typescript-jsx-router-vitest-playwright/tsconfig.node.json create mode 100644 playground/typescript-jsx-router-vitest-playwright/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-router-vitest-playwright/vite.config.ts create mode 100644 playground/typescript-jsx-router-vitest-playwright/vitest.config.ts create mode 100644 playground/typescript-jsx-router-vitest/.gitignore create mode 100644 playground/typescript-jsx-router-vitest/README.md create mode 100644 playground/typescript-jsx-router-vitest/env.d.ts create mode 100644 playground/typescript-jsx-router-vitest/index.html create mode 100644 playground/typescript-jsx-router-vitest/package.json create mode 100644 playground/typescript-jsx-router-vitest/public/favicon.ico create mode 100644 playground/typescript-jsx-router-vitest/src/App.vue create mode 100644 playground/typescript-jsx-router-vitest/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router-vitest/src/assets/main.css create mode 100644 playground/typescript-jsx-router-vitest/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router-vitest/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router-vitest/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router-vitest/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-router-vitest/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router-vitest/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router-vitest/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router-vitest/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router-vitest/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router-vitest/src/main.ts create mode 100644 playground/typescript-jsx-router-vitest/src/router/index.ts create mode 100644 playground/typescript-jsx-router-vitest/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router-vitest/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router-vitest/tsconfig.app.json create mode 100644 playground/typescript-jsx-router-vitest/tsconfig.json create mode 100644 playground/typescript-jsx-router-vitest/tsconfig.node.json create mode 100644 playground/typescript-jsx-router-vitest/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-router-vitest/vite.config.ts create mode 100644 playground/typescript-jsx-router-vitest/vitest.config.ts create mode 100644 playground/typescript-jsx-router-with-tests/.gitignore create mode 100644 playground/typescript-jsx-router-with-tests/README.md create mode 100644 playground/typescript-jsx-router-with-tests/cypress.config.ts create mode 100644 playground/typescript-jsx-router-with-tests/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-jsx-router-with-tests/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-router-with-tests/cypress/fixtures/example.json create mode 100644 playground/typescript-jsx-router-with-tests/cypress/support/commands.ts create mode 100644 playground/typescript-jsx-router-with-tests/cypress/support/e2e.ts create mode 100644 playground/typescript-jsx-router-with-tests/env.d.ts create mode 100644 playground/typescript-jsx-router-with-tests/index.html create mode 100644 playground/typescript-jsx-router-with-tests/package.json create mode 100644 playground/typescript-jsx-router-with-tests/public/favicon.ico create mode 100644 playground/typescript-jsx-router-with-tests/src/App.vue create mode 100644 playground/typescript-jsx-router-with-tests/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router-with-tests/src/assets/main.css create mode 100644 playground/typescript-jsx-router-with-tests/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router-with-tests/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router-with-tests/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router-with-tests/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-router-with-tests/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router-with-tests/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router-with-tests/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router-with-tests/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router-with-tests/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router-with-tests/src/main.ts create mode 100644 playground/typescript-jsx-router-with-tests/src/router/index.ts create mode 100644 playground/typescript-jsx-router-with-tests/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router-with-tests/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router-with-tests/tsconfig.app.json create mode 100644 playground/typescript-jsx-router-with-tests/tsconfig.json create mode 100644 playground/typescript-jsx-router-with-tests/tsconfig.node.json create mode 100644 playground/typescript-jsx-router-with-tests/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-router-with-tests/vite.config.ts create mode 100644 playground/typescript-jsx-router-with-tests/vitest.config.ts create mode 100644 playground/typescript-jsx-router/.gitignore create mode 100644 playground/typescript-jsx-router/README.md create mode 100644 playground/typescript-jsx-router/env.d.ts create mode 100644 playground/typescript-jsx-router/index.html create mode 100644 playground/typescript-jsx-router/package.json create mode 100644 playground/typescript-jsx-router/public/favicon.ico create mode 100644 playground/typescript-jsx-router/src/App.vue create mode 100644 playground/typescript-jsx-router/src/assets/logo.svg create mode 100644 playground/typescript-jsx-router/src/assets/main.css create mode 100644 playground/typescript-jsx-router/src/components/HelloWorld.vue create mode 100644 playground/typescript-jsx-router/src/components/TheWelcome.vue create mode 100644 playground/typescript-jsx-router/src/components/WelcomeItem.vue create mode 100644 playground/typescript-jsx-router/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-jsx-router/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-jsx-router/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-jsx-router/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-jsx-router/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-jsx-router/src/main.ts create mode 100644 playground/typescript-jsx-router/src/router/index.ts create mode 100644 playground/typescript-jsx-router/src/views/AboutView.vue create mode 100644 playground/typescript-jsx-router/src/views/HomeView.vue create mode 100644 playground/typescript-jsx-router/tsconfig.app.json create mode 100644 playground/typescript-jsx-router/tsconfig.json create mode 100644 playground/typescript-jsx-router/tsconfig.node.json create mode 100644 playground/typescript-jsx-router/vite.config.ts create mode 100644 playground/typescript-jsx-vitest-cypress/.gitignore create mode 100644 playground/typescript-jsx-vitest-cypress/README.md create mode 100644 playground/typescript-jsx-vitest-cypress/cypress.config.ts create mode 100644 playground/typescript-jsx-vitest-cypress/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-jsx-vitest-cypress/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-vitest-cypress/cypress/fixtures/example.json create mode 100644 playground/typescript-jsx-vitest-cypress/cypress/support/commands.ts create mode 100644 playground/typescript-jsx-vitest-cypress/cypress/support/e2e.ts create mode 100644 playground/typescript-jsx-vitest-cypress/env.d.ts create mode 100644 playground/typescript-jsx-vitest-cypress/index.html create mode 100644 playground/typescript-jsx-vitest-cypress/package.json create mode 100644 playground/typescript-jsx-vitest-cypress/public/favicon.ico create mode 100644 playground/typescript-jsx-vitest-cypress/src/App.vue create mode 100644 playground/typescript-jsx-vitest-cypress/src/assets/logo.svg create mode 100644 playground/typescript-jsx-vitest-cypress/src/assets/main.css create mode 100644 playground/typescript-jsx-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-vitest-cypress/src/main.ts create mode 100644 playground/typescript-jsx-vitest-cypress/tsconfig.app.json create mode 100644 playground/typescript-jsx-vitest-cypress/tsconfig.json create mode 100644 playground/typescript-jsx-vitest-cypress/tsconfig.node.json create mode 100644 playground/typescript-jsx-vitest-cypress/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-vitest-cypress/vite.config.ts create mode 100644 playground/typescript-jsx-vitest-cypress/vitest.config.ts create mode 100644 playground/typescript-jsx-vitest-nightwatch/.gitignore create mode 100644 playground/typescript-jsx-vitest-nightwatch/.vscode/extensions.json create mode 100644 playground/typescript-jsx-vitest-nightwatch/README.md create mode 100644 playground/typescript-jsx-vitest-nightwatch/env.d.ts create mode 100644 playground/typescript-jsx-vitest-nightwatch/index.html create mode 100644 playground/typescript-jsx-vitest-nightwatch/nightwatch.conf.cjs create mode 100644 playground/typescript-jsx-vitest-nightwatch/nightwatch/nightwatch.d.ts create mode 100644 playground/typescript-jsx-vitest-nightwatch/nightwatch/tsconfig.json create mode 100644 playground/typescript-jsx-vitest-nightwatch/package.json create mode 100644 playground/typescript-jsx-vitest-nightwatch/public/favicon.ico create mode 100644 playground/typescript-jsx-vitest-nightwatch/src/App.vue create mode 100644 playground/typescript-jsx-vitest-nightwatch/src/assets/logo.svg create mode 100644 playground/typescript-jsx-vitest-nightwatch/src/assets/main.css create mode 100644 playground/typescript-jsx-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-vitest-nightwatch/src/main.ts create mode 100644 playground/typescript-jsx-vitest-nightwatch/tests/e2e/example.ts create mode 100644 playground/typescript-jsx-vitest-nightwatch/tsconfig.app.json create mode 100644 playground/typescript-jsx-vitest-nightwatch/tsconfig.json create mode 100644 playground/typescript-jsx-vitest-nightwatch/tsconfig.node.json create mode 100644 playground/typescript-jsx-vitest-nightwatch/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-vitest-nightwatch/vite.config.ts create mode 100644 playground/typescript-jsx-vitest-nightwatch/vitest.config.ts create mode 100644 playground/typescript-jsx-vitest-playwright/.gitignore create mode 100644 playground/typescript-jsx-vitest-playwright/.vscode/extensions.json create mode 100644 playground/typescript-jsx-vitest-playwright/README.md create mode 100644 playground/typescript-jsx-vitest-playwright/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-vitest-playwright/e2e/vue.spec.ts create mode 100644 playground/typescript-jsx-vitest-playwright/env.d.ts create mode 100644 playground/typescript-jsx-vitest-playwright/index.html create mode 100644 playground/typescript-jsx-vitest-playwright/package.json create mode 100644 playground/typescript-jsx-vitest-playwright/playwright.config.ts create mode 100644 playground/typescript-jsx-vitest-playwright/public/favicon.ico create mode 100644 playground/typescript-jsx-vitest-playwright/src/App.vue create mode 100644 playground/typescript-jsx-vitest-playwright/src/assets/logo.svg create mode 100644 playground/typescript-jsx-vitest-playwright/src/assets/main.css create mode 100644 playground/typescript-jsx-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-vitest-playwright/src/main.ts create mode 100644 playground/typescript-jsx-vitest-playwright/tsconfig.app.json create mode 100644 playground/typescript-jsx-vitest-playwright/tsconfig.json create mode 100644 playground/typescript-jsx-vitest-playwright/tsconfig.node.json create mode 100644 playground/typescript-jsx-vitest-playwright/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-vitest-playwright/vite.config.ts create mode 100644 playground/typescript-jsx-vitest-playwright/vitest.config.ts create mode 100644 playground/typescript-jsx-vitest/.gitignore create mode 100644 playground/typescript-jsx-vitest/README.md create mode 100644 playground/typescript-jsx-vitest/env.d.ts create mode 100644 playground/typescript-jsx-vitest/index.html create mode 100644 playground/typescript-jsx-vitest/package.json create mode 100644 playground/typescript-jsx-vitest/public/favicon.ico create mode 100644 playground/typescript-jsx-vitest/src/App.vue create mode 100644 playground/typescript-jsx-vitest/src/assets/logo.svg create mode 100644 playground/typescript-jsx-vitest/src/assets/main.css create mode 100644 playground/typescript-jsx-vitest/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-vitest/src/main.ts create mode 100644 playground/typescript-jsx-vitest/tsconfig.app.json create mode 100644 playground/typescript-jsx-vitest/tsconfig.json create mode 100644 playground/typescript-jsx-vitest/tsconfig.node.json create mode 100644 playground/typescript-jsx-vitest/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-vitest/vite.config.ts create mode 100644 playground/typescript-jsx-vitest/vitest.config.ts create mode 100644 playground/typescript-jsx-with-tests/.gitignore create mode 100644 playground/typescript-jsx-with-tests/README.md create mode 100644 playground/typescript-jsx-with-tests/cypress.config.ts create mode 100644 playground/typescript-jsx-with-tests/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-jsx-with-tests/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-jsx-with-tests/cypress/fixtures/example.json create mode 100644 playground/typescript-jsx-with-tests/cypress/support/commands.ts create mode 100644 playground/typescript-jsx-with-tests/cypress/support/e2e.ts create mode 100644 playground/typescript-jsx-with-tests/env.d.ts create mode 100644 playground/typescript-jsx-with-tests/index.html create mode 100644 playground/typescript-jsx-with-tests/package.json create mode 100644 playground/typescript-jsx-with-tests/public/favicon.ico create mode 100644 playground/typescript-jsx-with-tests/src/App.vue create mode 100644 playground/typescript-jsx-with-tests/src/assets/logo.svg create mode 100644 playground/typescript-jsx-with-tests/src/assets/main.css create mode 100644 playground/typescript-jsx-with-tests/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-jsx-with-tests/src/main.ts create mode 100644 playground/typescript-jsx-with-tests/tsconfig.app.json create mode 100644 playground/typescript-jsx-with-tests/tsconfig.json create mode 100644 playground/typescript-jsx-with-tests/tsconfig.node.json create mode 100644 playground/typescript-jsx-with-tests/tsconfig.vitest.json create mode 100644 playground/typescript-jsx-with-tests/vite.config.ts create mode 100644 playground/typescript-jsx-with-tests/vitest.config.ts create mode 100644 playground/typescript-jsx/.gitignore create mode 100644 playground/typescript-jsx/README.md create mode 100644 playground/typescript-jsx/env.d.ts create mode 100644 playground/typescript-jsx/index.html create mode 100644 playground/typescript-jsx/package.json create mode 100644 playground/typescript-jsx/public/favicon.ico create mode 100644 playground/typescript-jsx/src/App.vue create mode 100644 playground/typescript-jsx/src/assets/logo.svg create mode 100644 playground/typescript-jsx/src/assets/main.css create mode 100644 playground/typescript-jsx/src/main.ts create mode 100644 playground/typescript-jsx/tsconfig.app.json create mode 100644 playground/typescript-jsx/tsconfig.json create mode 100644 playground/typescript-jsx/tsconfig.node.json create mode 100644 playground/typescript-jsx/vite.config.ts create mode 100644 playground/typescript-nightwatch/.gitignore create mode 100644 playground/typescript-nightwatch/.vscode/extensions.json create mode 100644 playground/typescript-nightwatch/README.md create mode 100644 playground/typescript-nightwatch/env.d.ts create mode 100644 playground/typescript-nightwatch/index.html create mode 100644 playground/typescript-nightwatch/nightwatch.conf.cjs create mode 100644 playground/typescript-nightwatch/nightwatch/index.html create mode 100644 playground/typescript-nightwatch/nightwatch/nightwatch.d.ts create mode 100644 playground/typescript-nightwatch/nightwatch/tsconfig.json create mode 100644 playground/typescript-nightwatch/package.json create mode 100644 playground/typescript-nightwatch/public/favicon.ico create mode 100644 playground/typescript-nightwatch/src/App.vue create mode 100644 playground/typescript-nightwatch/src/assets/logo.svg create mode 100644 playground/typescript-nightwatch/src/assets/main.css create mode 100644 playground/typescript-nightwatch/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-nightwatch/src/main.ts create mode 100644 playground/typescript-nightwatch/tests/e2e/example.ts create mode 100644 playground/typescript-nightwatch/tsconfig.app.json create mode 100644 playground/typescript-nightwatch/tsconfig.json create mode 100644 playground/typescript-nightwatch/tsconfig.node.json create mode 100644 playground/typescript-nightwatch/vite.config.ts create mode 100644 playground/typescript-pinia-cypress/.gitignore create mode 100644 playground/typescript-pinia-cypress/README.md create mode 100644 playground/typescript-pinia-cypress/cypress.config.ts create mode 100644 playground/typescript-pinia-cypress/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-pinia-cypress/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-pinia-cypress/cypress/fixtures/example.json create mode 100644 playground/typescript-pinia-cypress/cypress/support/commands.ts create mode 100644 playground/typescript-pinia-cypress/cypress/support/component-index.html create mode 100644 playground/typescript-pinia-cypress/cypress/support/component.ts create mode 100644 playground/typescript-pinia-cypress/cypress/support/e2e.ts create mode 100644 playground/typescript-pinia-cypress/env.d.ts create mode 100644 playground/typescript-pinia-cypress/index.html create mode 100644 playground/typescript-pinia-cypress/package.json create mode 100644 playground/typescript-pinia-cypress/public/favicon.ico create mode 100644 playground/typescript-pinia-cypress/src/App.vue create mode 100644 playground/typescript-pinia-cypress/src/assets/logo.svg create mode 100644 playground/typescript-pinia-cypress/src/assets/main.css create mode 100644 playground/typescript-pinia-cypress/src/components/__tests__/HelloWorld.cy.ts create mode 100644 playground/typescript-pinia-cypress/src/main.ts create mode 100644 playground/typescript-pinia-cypress/src/stores/counter.ts create mode 100644 playground/typescript-pinia-cypress/tsconfig.app.json create mode 100644 playground/typescript-pinia-cypress/tsconfig.cypress-ct.json create mode 100644 playground/typescript-pinia-cypress/tsconfig.json create mode 100644 playground/typescript-pinia-cypress/tsconfig.node.json create mode 100644 playground/typescript-pinia-cypress/vite.config.ts create mode 100644 playground/typescript-pinia-nightwatch/.gitignore create mode 100644 playground/typescript-pinia-nightwatch/.vscode/extensions.json create mode 100644 playground/typescript-pinia-nightwatch/README.md create mode 100644 playground/typescript-pinia-nightwatch/env.d.ts create mode 100644 playground/typescript-pinia-nightwatch/index.html create mode 100644 playground/typescript-pinia-nightwatch/nightwatch.conf.cjs create mode 100644 playground/typescript-pinia-nightwatch/nightwatch/index.html create mode 100644 playground/typescript-pinia-nightwatch/nightwatch/nightwatch.d.ts create mode 100644 playground/typescript-pinia-nightwatch/nightwatch/tsconfig.json create mode 100644 playground/typescript-pinia-nightwatch/package.json create mode 100644 playground/typescript-pinia-nightwatch/public/favicon.ico create mode 100644 playground/typescript-pinia-nightwatch/src/App.vue create mode 100644 playground/typescript-pinia-nightwatch/src/assets/logo.svg create mode 100644 playground/typescript-pinia-nightwatch/src/assets/main.css create mode 100644 playground/typescript-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-pinia-nightwatch/src/main.ts create mode 100644 playground/typescript-pinia-nightwatch/src/stores/counter.ts create mode 100644 playground/typescript-pinia-nightwatch/tests/e2e/example.ts create mode 100644 playground/typescript-pinia-nightwatch/tsconfig.app.json create mode 100644 playground/typescript-pinia-nightwatch/tsconfig.json create mode 100644 playground/typescript-pinia-nightwatch/tsconfig.node.json create mode 100644 playground/typescript-pinia-nightwatch/vite.config.ts create mode 100644 playground/typescript-pinia-playwright/.gitignore create mode 100644 playground/typescript-pinia-playwright/.vscode/extensions.json create mode 100644 playground/typescript-pinia-playwright/README.md create mode 100644 playground/typescript-pinia-playwright/e2e/tsconfig.json create mode 100644 playground/typescript-pinia-playwright/e2e/vue.spec.ts create mode 100644 playground/typescript-pinia-playwright/env.d.ts create mode 100644 playground/typescript-pinia-playwright/index.html create mode 100644 playground/typescript-pinia-playwright/package.json create mode 100644 playground/typescript-pinia-playwright/playwright.config.ts create mode 100644 playground/typescript-pinia-playwright/public/favicon.ico create mode 100644 playground/typescript-pinia-playwright/src/App.vue create mode 100644 playground/typescript-pinia-playwright/src/assets/logo.svg create mode 100644 playground/typescript-pinia-playwright/src/assets/main.css create mode 100644 playground/typescript-pinia-playwright/src/main.ts create mode 100644 playground/typescript-pinia-playwright/src/stores/counter.ts create mode 100644 playground/typescript-pinia-playwright/tsconfig.app.json create mode 100644 playground/typescript-pinia-playwright/tsconfig.json create mode 100644 playground/typescript-pinia-playwright/tsconfig.node.json create mode 100644 playground/typescript-pinia-playwright/vite.config.ts create mode 100644 playground/typescript-pinia-vitest-cypress/.gitignore create mode 100644 playground/typescript-pinia-vitest-cypress/README.md create mode 100644 playground/typescript-pinia-vitest-cypress/cypress.config.ts create mode 100644 playground/typescript-pinia-vitest-cypress/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-pinia-vitest-cypress/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-pinia-vitest-cypress/cypress/fixtures/example.json create mode 100644 playground/typescript-pinia-vitest-cypress/cypress/support/commands.ts create mode 100644 playground/typescript-pinia-vitest-cypress/cypress/support/e2e.ts create mode 100644 playground/typescript-pinia-vitest-cypress/env.d.ts create mode 100644 playground/typescript-pinia-vitest-cypress/index.html create mode 100644 playground/typescript-pinia-vitest-cypress/package.json create mode 100644 playground/typescript-pinia-vitest-cypress/public/favicon.ico create mode 100644 playground/typescript-pinia-vitest-cypress/src/App.vue create mode 100644 playground/typescript-pinia-vitest-cypress/src/assets/logo.svg create mode 100644 playground/typescript-pinia-vitest-cypress/src/assets/main.css create mode 100644 playground/typescript-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-pinia-vitest-cypress/src/main.ts create mode 100644 playground/typescript-pinia-vitest-cypress/src/stores/counter.ts create mode 100644 playground/typescript-pinia-vitest-cypress/tsconfig.app.json create mode 100644 playground/typescript-pinia-vitest-cypress/tsconfig.json create mode 100644 playground/typescript-pinia-vitest-cypress/tsconfig.node.json create mode 100644 playground/typescript-pinia-vitest-cypress/tsconfig.vitest.json create mode 100644 playground/typescript-pinia-vitest-cypress/vite.config.ts create mode 100644 playground/typescript-pinia-vitest-cypress/vitest.config.ts create mode 100644 playground/typescript-pinia-vitest-nightwatch/.gitignore create mode 100644 playground/typescript-pinia-vitest-nightwatch/.vscode/extensions.json create mode 100644 playground/typescript-pinia-vitest-nightwatch/README.md create mode 100644 playground/typescript-pinia-vitest-nightwatch/env.d.ts create mode 100644 playground/typescript-pinia-vitest-nightwatch/index.html create mode 100644 playground/typescript-pinia-vitest-nightwatch/nightwatch.conf.cjs create mode 100644 playground/typescript-pinia-vitest-nightwatch/nightwatch/nightwatch.d.ts create mode 100644 playground/typescript-pinia-vitest-nightwatch/nightwatch/tsconfig.json create mode 100644 playground/typescript-pinia-vitest-nightwatch/package.json create mode 100644 playground/typescript-pinia-vitest-nightwatch/public/favicon.ico create mode 100644 playground/typescript-pinia-vitest-nightwatch/src/App.vue create mode 100644 playground/typescript-pinia-vitest-nightwatch/src/assets/logo.svg create mode 100644 playground/typescript-pinia-vitest-nightwatch/src/assets/main.css create mode 100644 playground/typescript-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-pinia-vitest-nightwatch/src/main.ts create mode 100644 playground/typescript-pinia-vitest-nightwatch/src/stores/counter.ts create mode 100644 playground/typescript-pinia-vitest-nightwatch/tests/e2e/example.ts create mode 100644 playground/typescript-pinia-vitest-nightwatch/tsconfig.app.json create mode 100644 playground/typescript-pinia-vitest-nightwatch/tsconfig.json create mode 100644 playground/typescript-pinia-vitest-nightwatch/tsconfig.node.json create mode 100644 playground/typescript-pinia-vitest-nightwatch/tsconfig.vitest.json create mode 100644 playground/typescript-pinia-vitest-nightwatch/vite.config.ts create mode 100644 playground/typescript-pinia-vitest-nightwatch/vitest.config.ts create mode 100644 playground/typescript-pinia-vitest-playwright/.gitignore create mode 100644 playground/typescript-pinia-vitest-playwright/.vscode/extensions.json create mode 100644 playground/typescript-pinia-vitest-playwright/README.md create mode 100644 playground/typescript-pinia-vitest-playwright/e2e/tsconfig.json create mode 100644 playground/typescript-pinia-vitest-playwright/e2e/vue.spec.ts create mode 100644 playground/typescript-pinia-vitest-playwright/env.d.ts create mode 100644 playground/typescript-pinia-vitest-playwright/index.html create mode 100644 playground/typescript-pinia-vitest-playwright/package.json create mode 100644 playground/typescript-pinia-vitest-playwright/playwright.config.ts create mode 100644 playground/typescript-pinia-vitest-playwright/public/favicon.ico create mode 100644 playground/typescript-pinia-vitest-playwright/src/App.vue create mode 100644 playground/typescript-pinia-vitest-playwright/src/assets/logo.svg create mode 100644 playground/typescript-pinia-vitest-playwright/src/assets/main.css create mode 100644 playground/typescript-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-pinia-vitest-playwright/src/main.ts create mode 100644 playground/typescript-pinia-vitest-playwright/src/stores/counter.ts create mode 100644 playground/typescript-pinia-vitest-playwright/tsconfig.app.json create mode 100644 playground/typescript-pinia-vitest-playwright/tsconfig.json create mode 100644 playground/typescript-pinia-vitest-playwright/tsconfig.node.json create mode 100644 playground/typescript-pinia-vitest-playwright/tsconfig.vitest.json create mode 100644 playground/typescript-pinia-vitest-playwright/vite.config.ts create mode 100644 playground/typescript-pinia-vitest-playwright/vitest.config.ts create mode 100644 playground/typescript-pinia-vitest/.gitignore create mode 100644 playground/typescript-pinia-vitest/README.md create mode 100644 playground/typescript-pinia-vitest/env.d.ts create mode 100644 playground/typescript-pinia-vitest/index.html create mode 100644 playground/typescript-pinia-vitest/package.json create mode 100644 playground/typescript-pinia-vitest/public/favicon.ico create mode 100644 playground/typescript-pinia-vitest/src/App.vue create mode 100644 playground/typescript-pinia-vitest/src/assets/logo.svg create mode 100644 playground/typescript-pinia-vitest/src/assets/main.css create mode 100644 playground/typescript-pinia-vitest/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-pinia-vitest/src/main.ts create mode 100644 playground/typescript-pinia-vitest/src/stores/counter.ts create mode 100644 playground/typescript-pinia-vitest/tsconfig.app.json create mode 100644 playground/typescript-pinia-vitest/tsconfig.json create mode 100644 playground/typescript-pinia-vitest/tsconfig.node.json create mode 100644 playground/typescript-pinia-vitest/tsconfig.vitest.json create mode 100644 playground/typescript-pinia-vitest/vite.config.ts create mode 100644 playground/typescript-pinia-vitest/vitest.config.ts create mode 100644 playground/typescript-pinia-with-tests/.gitignore create mode 100644 playground/typescript-pinia-with-tests/README.md create mode 100644 playground/typescript-pinia-with-tests/cypress.config.ts create mode 100644 playground/typescript-pinia-with-tests/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-pinia-with-tests/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-pinia-with-tests/cypress/fixtures/example.json create mode 100644 playground/typescript-pinia-with-tests/cypress/support/commands.ts create mode 100644 playground/typescript-pinia-with-tests/cypress/support/e2e.ts create mode 100644 playground/typescript-pinia-with-tests/env.d.ts create mode 100644 playground/typescript-pinia-with-tests/index.html create mode 100644 playground/typescript-pinia-with-tests/package.json create mode 100644 playground/typescript-pinia-with-tests/public/favicon.ico create mode 100644 playground/typescript-pinia-with-tests/src/App.vue create mode 100644 playground/typescript-pinia-with-tests/src/assets/logo.svg create mode 100644 playground/typescript-pinia-with-tests/src/assets/main.css create mode 100644 playground/typescript-pinia-with-tests/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-pinia-with-tests/src/main.ts create mode 100644 playground/typescript-pinia-with-tests/src/stores/counter.ts create mode 100644 playground/typescript-pinia-with-tests/tsconfig.app.json create mode 100644 playground/typescript-pinia-with-tests/tsconfig.json create mode 100644 playground/typescript-pinia-with-tests/tsconfig.node.json create mode 100644 playground/typescript-pinia-with-tests/tsconfig.vitest.json create mode 100644 playground/typescript-pinia-with-tests/vite.config.ts create mode 100644 playground/typescript-pinia-with-tests/vitest.config.ts create mode 100644 playground/typescript-pinia/.gitignore create mode 100644 playground/typescript-pinia/README.md create mode 100644 playground/typescript-pinia/env.d.ts create mode 100644 playground/typescript-pinia/index.html create mode 100644 playground/typescript-pinia/package.json create mode 100644 playground/typescript-pinia/public/favicon.ico create mode 100644 playground/typescript-pinia/src/App.vue create mode 100644 playground/typescript-pinia/src/assets/logo.svg create mode 100644 playground/typescript-pinia/src/assets/main.css create mode 100644 playground/typescript-pinia/src/main.ts create mode 100644 playground/typescript-pinia/src/stores/counter.ts create mode 100644 playground/typescript-pinia/tsconfig.app.json create mode 100644 playground/typescript-pinia/tsconfig.json create mode 100644 playground/typescript-pinia/tsconfig.node.json create mode 100644 playground/typescript-pinia/vite.config.ts create mode 100644 playground/typescript-playwright/.gitignore create mode 100644 playground/typescript-playwright/.vscode/extensions.json create mode 100644 playground/typescript-playwright/README.md create mode 100644 playground/typescript-playwright/e2e/tsconfig.json create mode 100644 playground/typescript-playwright/e2e/vue.spec.ts create mode 100644 playground/typescript-playwright/env.d.ts create mode 100644 playground/typescript-playwright/index.html create mode 100644 playground/typescript-playwright/package.json create mode 100644 playground/typescript-playwright/playwright.config.ts create mode 100644 playground/typescript-playwright/public/favicon.ico create mode 100644 playground/typescript-playwright/src/App.vue create mode 100644 playground/typescript-playwright/src/assets/logo.svg create mode 100644 playground/typescript-playwright/src/assets/main.css create mode 100644 playground/typescript-playwright/src/main.ts create mode 100644 playground/typescript-playwright/tsconfig.app.json create mode 100644 playground/typescript-playwright/tsconfig.json create mode 100644 playground/typescript-playwright/tsconfig.node.json create mode 100644 playground/typescript-playwright/vite.config.ts create mode 100644 playground/typescript-router-cypress/.gitignore create mode 100644 playground/typescript-router-cypress/README.md create mode 100644 playground/typescript-router-cypress/cypress.config.ts create mode 100644 playground/typescript-router-cypress/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-router-cypress/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-router-cypress/cypress/fixtures/example.json create mode 100644 playground/typescript-router-cypress/cypress/support/commands.ts create mode 100644 playground/typescript-router-cypress/cypress/support/component-index.html create mode 100644 playground/typescript-router-cypress/cypress/support/component.ts create mode 100644 playground/typescript-router-cypress/cypress/support/e2e.ts create mode 100644 playground/typescript-router-cypress/env.d.ts create mode 100644 playground/typescript-router-cypress/index.html create mode 100644 playground/typescript-router-cypress/package.json create mode 100644 playground/typescript-router-cypress/public/favicon.ico create mode 100644 playground/typescript-router-cypress/src/App.vue create mode 100644 playground/typescript-router-cypress/src/assets/logo.svg create mode 100644 playground/typescript-router-cypress/src/assets/main.css create mode 100644 playground/typescript-router-cypress/src/components/HelloWorld.vue create mode 100644 playground/typescript-router-cypress/src/components/TheWelcome.vue create mode 100644 playground/typescript-router-cypress/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router-cypress/src/components/__tests__/HelloWorld.cy.ts create mode 100644 playground/typescript-router-cypress/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router-cypress/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router-cypress/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router-cypress/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router-cypress/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router-cypress/src/main.ts create mode 100644 playground/typescript-router-cypress/src/router/index.ts create mode 100644 playground/typescript-router-cypress/src/views/AboutView.vue create mode 100644 playground/typescript-router-cypress/src/views/HomeView.vue create mode 100644 playground/typescript-router-cypress/tsconfig.app.json create mode 100644 playground/typescript-router-cypress/tsconfig.cypress-ct.json create mode 100644 playground/typescript-router-cypress/tsconfig.json create mode 100644 playground/typescript-router-cypress/tsconfig.node.json create mode 100644 playground/typescript-router-cypress/vite.config.ts create mode 100644 playground/typescript-router-nightwatch/.gitignore create mode 100644 playground/typescript-router-nightwatch/.vscode/extensions.json create mode 100644 playground/typescript-router-nightwatch/README.md create mode 100644 playground/typescript-router-nightwatch/env.d.ts create mode 100644 playground/typescript-router-nightwatch/index.html create mode 100644 playground/typescript-router-nightwatch/nightwatch.conf.cjs create mode 100644 playground/typescript-router-nightwatch/nightwatch/index.html create mode 100644 playground/typescript-router-nightwatch/nightwatch/nightwatch.d.ts create mode 100644 playground/typescript-router-nightwatch/nightwatch/tsconfig.json create mode 100644 playground/typescript-router-nightwatch/package.json create mode 100644 playground/typescript-router-nightwatch/public/favicon.ico create mode 100644 playground/typescript-router-nightwatch/src/App.vue create mode 100644 playground/typescript-router-nightwatch/src/assets/logo.svg create mode 100644 playground/typescript-router-nightwatch/src/assets/main.css create mode 100644 playground/typescript-router-nightwatch/src/components/HelloWorld.vue create mode 100644 playground/typescript-router-nightwatch/src/components/TheWelcome.vue create mode 100644 playground/typescript-router-nightwatch/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router-nightwatch/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-router-nightwatch/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router-nightwatch/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router-nightwatch/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router-nightwatch/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router-nightwatch/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router-nightwatch/src/main.ts create mode 100644 playground/typescript-router-nightwatch/src/router/index.ts create mode 100644 playground/typescript-router-nightwatch/src/views/AboutView.vue create mode 100644 playground/typescript-router-nightwatch/src/views/HomeView.vue create mode 100644 playground/typescript-router-nightwatch/tests/e2e/example.ts create mode 100644 playground/typescript-router-nightwatch/tsconfig.app.json create mode 100644 playground/typescript-router-nightwatch/tsconfig.json create mode 100644 playground/typescript-router-nightwatch/tsconfig.node.json create mode 100644 playground/typescript-router-nightwatch/vite.config.ts create mode 100644 playground/typescript-router-pinia-cypress/.gitignore create mode 100644 playground/typescript-router-pinia-cypress/README.md create mode 100644 playground/typescript-router-pinia-cypress/cypress.config.ts create mode 100644 playground/typescript-router-pinia-cypress/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-router-pinia-cypress/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-router-pinia-cypress/cypress/fixtures/example.json create mode 100644 playground/typescript-router-pinia-cypress/cypress/support/commands.ts create mode 100644 playground/typescript-router-pinia-cypress/cypress/support/component-index.html create mode 100644 playground/typescript-router-pinia-cypress/cypress/support/component.ts create mode 100644 playground/typescript-router-pinia-cypress/cypress/support/e2e.ts create mode 100644 playground/typescript-router-pinia-cypress/env.d.ts create mode 100644 playground/typescript-router-pinia-cypress/index.html create mode 100644 playground/typescript-router-pinia-cypress/package.json create mode 100644 playground/typescript-router-pinia-cypress/public/favicon.ico create mode 100644 playground/typescript-router-pinia-cypress/src/App.vue create mode 100644 playground/typescript-router-pinia-cypress/src/assets/logo.svg create mode 100644 playground/typescript-router-pinia-cypress/src/assets/main.css create mode 100644 playground/typescript-router-pinia-cypress/src/components/HelloWorld.vue create mode 100644 playground/typescript-router-pinia-cypress/src/components/TheWelcome.vue create mode 100644 playground/typescript-router-pinia-cypress/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router-pinia-cypress/src/components/__tests__/HelloWorld.cy.ts create mode 100644 playground/typescript-router-pinia-cypress/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router-pinia-cypress/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router-pinia-cypress/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router-pinia-cypress/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router-pinia-cypress/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router-pinia-cypress/src/main.ts create mode 100644 playground/typescript-router-pinia-cypress/src/router/index.ts create mode 100644 playground/typescript-router-pinia-cypress/src/stores/counter.ts create mode 100644 playground/typescript-router-pinia-cypress/src/views/AboutView.vue create mode 100644 playground/typescript-router-pinia-cypress/src/views/HomeView.vue create mode 100644 playground/typescript-router-pinia-cypress/tsconfig.app.json create mode 100644 playground/typescript-router-pinia-cypress/tsconfig.cypress-ct.json create mode 100644 playground/typescript-router-pinia-cypress/tsconfig.json create mode 100644 playground/typescript-router-pinia-cypress/tsconfig.node.json create mode 100644 playground/typescript-router-pinia-cypress/vite.config.ts create mode 100644 playground/typescript-router-pinia-nightwatch/.gitignore create mode 100644 playground/typescript-router-pinia-nightwatch/.vscode/extensions.json create mode 100644 playground/typescript-router-pinia-nightwatch/README.md create mode 100644 playground/typescript-router-pinia-nightwatch/env.d.ts create mode 100644 playground/typescript-router-pinia-nightwatch/index.html create mode 100644 playground/typescript-router-pinia-nightwatch/nightwatch.conf.cjs create mode 100644 playground/typescript-router-pinia-nightwatch/nightwatch/index.html create mode 100644 playground/typescript-router-pinia-nightwatch/nightwatch/nightwatch.d.ts create mode 100644 playground/typescript-router-pinia-nightwatch/nightwatch/tsconfig.json create mode 100644 playground/typescript-router-pinia-nightwatch/package.json create mode 100644 playground/typescript-router-pinia-nightwatch/public/favicon.ico create mode 100644 playground/typescript-router-pinia-nightwatch/src/App.vue create mode 100644 playground/typescript-router-pinia-nightwatch/src/assets/logo.svg create mode 100644 playground/typescript-router-pinia-nightwatch/src/assets/main.css create mode 100644 playground/typescript-router-pinia-nightwatch/src/components/HelloWorld.vue create mode 100644 playground/typescript-router-pinia-nightwatch/src/components/TheWelcome.vue create mode 100644 playground/typescript-router-pinia-nightwatch/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-router-pinia-nightwatch/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router-pinia-nightwatch/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router-pinia-nightwatch/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router-pinia-nightwatch/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router-pinia-nightwatch/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router-pinia-nightwatch/src/main.ts create mode 100644 playground/typescript-router-pinia-nightwatch/src/router/index.ts create mode 100644 playground/typescript-router-pinia-nightwatch/src/stores/counter.ts create mode 100644 playground/typescript-router-pinia-nightwatch/src/views/AboutView.vue create mode 100644 playground/typescript-router-pinia-nightwatch/src/views/HomeView.vue create mode 100644 playground/typescript-router-pinia-nightwatch/tests/e2e/example.ts create mode 100644 playground/typescript-router-pinia-nightwatch/tsconfig.app.json create mode 100644 playground/typescript-router-pinia-nightwatch/tsconfig.json create mode 100644 playground/typescript-router-pinia-nightwatch/tsconfig.node.json create mode 100644 playground/typescript-router-pinia-nightwatch/vite.config.ts create mode 100644 playground/typescript-router-pinia-playwright/.gitignore create mode 100644 playground/typescript-router-pinia-playwright/.vscode/extensions.json create mode 100644 playground/typescript-router-pinia-playwright/README.md create mode 100644 playground/typescript-router-pinia-playwright/e2e/tsconfig.json create mode 100644 playground/typescript-router-pinia-playwright/e2e/vue.spec.ts create mode 100644 playground/typescript-router-pinia-playwright/env.d.ts create mode 100644 playground/typescript-router-pinia-playwright/index.html create mode 100644 playground/typescript-router-pinia-playwright/package.json create mode 100644 playground/typescript-router-pinia-playwright/playwright.config.ts create mode 100644 playground/typescript-router-pinia-playwright/public/favicon.ico create mode 100644 playground/typescript-router-pinia-playwright/src/App.vue create mode 100644 playground/typescript-router-pinia-playwright/src/assets/logo.svg create mode 100644 playground/typescript-router-pinia-playwright/src/assets/main.css create mode 100644 playground/typescript-router-pinia-playwright/src/components/HelloWorld.vue create mode 100644 playground/typescript-router-pinia-playwright/src/components/TheWelcome.vue create mode 100644 playground/typescript-router-pinia-playwright/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router-pinia-playwright/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router-pinia-playwright/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router-pinia-playwright/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router-pinia-playwright/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router-pinia-playwright/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router-pinia-playwright/src/main.ts create mode 100644 playground/typescript-router-pinia-playwright/src/router/index.ts create mode 100644 playground/typescript-router-pinia-playwright/src/stores/counter.ts create mode 100644 playground/typescript-router-pinia-playwright/src/views/AboutView.vue create mode 100644 playground/typescript-router-pinia-playwright/src/views/HomeView.vue create mode 100644 playground/typescript-router-pinia-playwright/tsconfig.app.json create mode 100644 playground/typescript-router-pinia-playwright/tsconfig.json create mode 100644 playground/typescript-router-pinia-playwright/tsconfig.node.json create mode 100644 playground/typescript-router-pinia-playwright/vite.config.ts create mode 100644 playground/typescript-router-pinia-vitest-cypress/.gitignore create mode 100644 playground/typescript-router-pinia-vitest-cypress/README.md create mode 100644 playground/typescript-router-pinia-vitest-cypress/cypress.config.ts create mode 100644 playground/typescript-router-pinia-vitest-cypress/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-router-pinia-vitest-cypress/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-router-pinia-vitest-cypress/cypress/fixtures/example.json create mode 100644 playground/typescript-router-pinia-vitest-cypress/cypress/support/commands.ts create mode 100644 playground/typescript-router-pinia-vitest-cypress/cypress/support/e2e.ts create mode 100644 playground/typescript-router-pinia-vitest-cypress/env.d.ts create mode 100644 playground/typescript-router-pinia-vitest-cypress/index.html create mode 100644 playground/typescript-router-pinia-vitest-cypress/package.json create mode 100644 playground/typescript-router-pinia-vitest-cypress/public/favicon.ico create mode 100644 playground/typescript-router-pinia-vitest-cypress/src/App.vue create mode 100644 playground/typescript-router-pinia-vitest-cypress/src/assets/logo.svg create mode 100644 playground/typescript-router-pinia-vitest-cypress/src/assets/main.css create mode 100644 playground/typescript-router-pinia-vitest-cypress/src/components/HelloWorld.vue create mode 100644 playground/typescript-router-pinia-vitest-cypress/src/components/TheWelcome.vue create mode 100644 playground/typescript-router-pinia-vitest-cypress/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router-pinia-vitest-cypress/src/main.ts create mode 100644 playground/typescript-router-pinia-vitest-cypress/src/router/index.ts create mode 100644 playground/typescript-router-pinia-vitest-cypress/src/stores/counter.ts create mode 100644 playground/typescript-router-pinia-vitest-cypress/src/views/AboutView.vue create mode 100644 playground/typescript-router-pinia-vitest-cypress/src/views/HomeView.vue create mode 100644 playground/typescript-router-pinia-vitest-cypress/tsconfig.app.json create mode 100644 playground/typescript-router-pinia-vitest-cypress/tsconfig.json create mode 100644 playground/typescript-router-pinia-vitest-cypress/tsconfig.node.json create mode 100644 playground/typescript-router-pinia-vitest-cypress/tsconfig.vitest.json create mode 100644 playground/typescript-router-pinia-vitest-cypress/vite.config.ts create mode 100644 playground/typescript-router-pinia-vitest-cypress/vitest.config.ts create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/.gitignore create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/.vscode/extensions.json create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/README.md create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/env.d.ts create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/index.html create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/nightwatch.conf.cjs create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/nightwatch/nightwatch.d.ts create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/nightwatch/tsconfig.json create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/package.json create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/public/favicon.ico create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/src/App.vue create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/src/assets/logo.svg create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/src/assets/main.css create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/src/components/HelloWorld.vue create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/src/components/TheWelcome.vue create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/src/main.ts create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/src/router/index.ts create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/src/stores/counter.ts create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/src/views/AboutView.vue create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/src/views/HomeView.vue create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/tests/e2e/example.ts create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/tsconfig.app.json create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/tsconfig.json create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/tsconfig.node.json create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/tsconfig.vitest.json create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/vite.config.ts create mode 100644 playground/typescript-router-pinia-vitest-nightwatch/vitest.config.ts create mode 100644 playground/typescript-router-pinia-vitest-playwright/.gitignore create mode 100644 playground/typescript-router-pinia-vitest-playwright/.vscode/extensions.json create mode 100644 playground/typescript-router-pinia-vitest-playwright/README.md create mode 100644 playground/typescript-router-pinia-vitest-playwright/e2e/tsconfig.json create mode 100644 playground/typescript-router-pinia-vitest-playwright/e2e/vue.spec.ts create mode 100644 playground/typescript-router-pinia-vitest-playwright/env.d.ts create mode 100644 playground/typescript-router-pinia-vitest-playwright/index.html create mode 100644 playground/typescript-router-pinia-vitest-playwright/package.json create mode 100644 playground/typescript-router-pinia-vitest-playwright/playwright.config.ts create mode 100644 playground/typescript-router-pinia-vitest-playwright/public/favicon.ico create mode 100644 playground/typescript-router-pinia-vitest-playwright/src/App.vue create mode 100644 playground/typescript-router-pinia-vitest-playwright/src/assets/logo.svg create mode 100644 playground/typescript-router-pinia-vitest-playwright/src/assets/main.css create mode 100644 playground/typescript-router-pinia-vitest-playwright/src/components/HelloWorld.vue create mode 100644 playground/typescript-router-pinia-vitest-playwright/src/components/TheWelcome.vue create mode 100644 playground/typescript-router-pinia-vitest-playwright/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router-pinia-vitest-playwright/src/main.ts create mode 100644 playground/typescript-router-pinia-vitest-playwright/src/router/index.ts create mode 100644 playground/typescript-router-pinia-vitest-playwright/src/stores/counter.ts create mode 100644 playground/typescript-router-pinia-vitest-playwright/src/views/AboutView.vue create mode 100644 playground/typescript-router-pinia-vitest-playwright/src/views/HomeView.vue create mode 100644 playground/typescript-router-pinia-vitest-playwright/tsconfig.app.json create mode 100644 playground/typescript-router-pinia-vitest-playwright/tsconfig.json create mode 100644 playground/typescript-router-pinia-vitest-playwright/tsconfig.node.json create mode 100644 playground/typescript-router-pinia-vitest-playwright/tsconfig.vitest.json create mode 100644 playground/typescript-router-pinia-vitest-playwright/vite.config.ts create mode 100644 playground/typescript-router-pinia-vitest-playwright/vitest.config.ts create mode 100644 playground/typescript-router-pinia-vitest/.gitignore create mode 100644 playground/typescript-router-pinia-vitest/README.md create mode 100644 playground/typescript-router-pinia-vitest/env.d.ts create mode 100644 playground/typescript-router-pinia-vitest/index.html create mode 100644 playground/typescript-router-pinia-vitest/package.json create mode 100644 playground/typescript-router-pinia-vitest/public/favicon.ico create mode 100644 playground/typescript-router-pinia-vitest/src/App.vue create mode 100644 playground/typescript-router-pinia-vitest/src/assets/logo.svg create mode 100644 playground/typescript-router-pinia-vitest/src/assets/main.css create mode 100644 playground/typescript-router-pinia-vitest/src/components/HelloWorld.vue create mode 100644 playground/typescript-router-pinia-vitest/src/components/TheWelcome.vue create mode 100644 playground/typescript-router-pinia-vitest/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router-pinia-vitest/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-router-pinia-vitest/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router-pinia-vitest/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router-pinia-vitest/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router-pinia-vitest/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router-pinia-vitest/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router-pinia-vitest/src/main.ts create mode 100644 playground/typescript-router-pinia-vitest/src/router/index.ts create mode 100644 playground/typescript-router-pinia-vitest/src/stores/counter.ts create mode 100644 playground/typescript-router-pinia-vitest/src/views/AboutView.vue create mode 100644 playground/typescript-router-pinia-vitest/src/views/HomeView.vue create mode 100644 playground/typescript-router-pinia-vitest/tsconfig.app.json create mode 100644 playground/typescript-router-pinia-vitest/tsconfig.json create mode 100644 playground/typescript-router-pinia-vitest/tsconfig.node.json create mode 100644 playground/typescript-router-pinia-vitest/tsconfig.vitest.json create mode 100644 playground/typescript-router-pinia-vitest/vite.config.ts create mode 100644 playground/typescript-router-pinia-vitest/vitest.config.ts create mode 100644 playground/typescript-router-pinia-with-tests/.gitignore create mode 100644 playground/typescript-router-pinia-with-tests/README.md create mode 100644 playground/typescript-router-pinia-with-tests/cypress.config.ts create mode 100644 playground/typescript-router-pinia-with-tests/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-router-pinia-with-tests/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-router-pinia-with-tests/cypress/fixtures/example.json create mode 100644 playground/typescript-router-pinia-with-tests/cypress/support/commands.ts create mode 100644 playground/typescript-router-pinia-with-tests/cypress/support/e2e.ts create mode 100644 playground/typescript-router-pinia-with-tests/env.d.ts create mode 100644 playground/typescript-router-pinia-with-tests/index.html create mode 100644 playground/typescript-router-pinia-with-tests/package.json create mode 100644 playground/typescript-router-pinia-with-tests/public/favicon.ico create mode 100644 playground/typescript-router-pinia-with-tests/src/App.vue create mode 100644 playground/typescript-router-pinia-with-tests/src/assets/logo.svg create mode 100644 playground/typescript-router-pinia-with-tests/src/assets/main.css create mode 100644 playground/typescript-router-pinia-with-tests/src/components/HelloWorld.vue create mode 100644 playground/typescript-router-pinia-with-tests/src/components/TheWelcome.vue create mode 100644 playground/typescript-router-pinia-with-tests/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router-pinia-with-tests/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-router-pinia-with-tests/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router-pinia-with-tests/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router-pinia-with-tests/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router-pinia-with-tests/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router-pinia-with-tests/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router-pinia-with-tests/src/main.ts create mode 100644 playground/typescript-router-pinia-with-tests/src/router/index.ts create mode 100644 playground/typescript-router-pinia-with-tests/src/stores/counter.ts create mode 100644 playground/typescript-router-pinia-with-tests/src/views/AboutView.vue create mode 100644 playground/typescript-router-pinia-with-tests/src/views/HomeView.vue create mode 100644 playground/typescript-router-pinia-with-tests/tsconfig.app.json create mode 100644 playground/typescript-router-pinia-with-tests/tsconfig.json create mode 100644 playground/typescript-router-pinia-with-tests/tsconfig.node.json create mode 100644 playground/typescript-router-pinia-with-tests/tsconfig.vitest.json create mode 100644 playground/typescript-router-pinia-with-tests/vite.config.ts create mode 100644 playground/typescript-router-pinia-with-tests/vitest.config.ts create mode 100644 playground/typescript-router-pinia/.gitignore create mode 100644 playground/typescript-router-pinia/README.md create mode 100644 playground/typescript-router-pinia/env.d.ts create mode 100644 playground/typescript-router-pinia/index.html create mode 100644 playground/typescript-router-pinia/package.json create mode 100644 playground/typescript-router-pinia/public/favicon.ico create mode 100644 playground/typescript-router-pinia/src/App.vue create mode 100644 playground/typescript-router-pinia/src/assets/logo.svg create mode 100644 playground/typescript-router-pinia/src/assets/main.css create mode 100644 playground/typescript-router-pinia/src/components/HelloWorld.vue create mode 100644 playground/typescript-router-pinia/src/components/TheWelcome.vue create mode 100644 playground/typescript-router-pinia/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router-pinia/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router-pinia/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router-pinia/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router-pinia/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router-pinia/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router-pinia/src/main.ts create mode 100644 playground/typescript-router-pinia/src/router/index.ts create mode 100644 playground/typescript-router-pinia/src/stores/counter.ts create mode 100644 playground/typescript-router-pinia/src/views/AboutView.vue create mode 100644 playground/typescript-router-pinia/src/views/HomeView.vue create mode 100644 playground/typescript-router-pinia/tsconfig.app.json create mode 100644 playground/typescript-router-pinia/tsconfig.json create mode 100644 playground/typescript-router-pinia/tsconfig.node.json create mode 100644 playground/typescript-router-pinia/vite.config.ts create mode 100644 playground/typescript-router-playwright/.gitignore create mode 100644 playground/typescript-router-playwright/.vscode/extensions.json create mode 100644 playground/typescript-router-playwright/README.md create mode 100644 playground/typescript-router-playwright/e2e/tsconfig.json create mode 100644 playground/typescript-router-playwright/e2e/vue.spec.ts create mode 100644 playground/typescript-router-playwright/env.d.ts create mode 100644 playground/typescript-router-playwright/index.html create mode 100644 playground/typescript-router-playwright/package.json create mode 100644 playground/typescript-router-playwright/playwright.config.ts create mode 100644 playground/typescript-router-playwright/public/favicon.ico create mode 100644 playground/typescript-router-playwright/src/App.vue create mode 100644 playground/typescript-router-playwright/src/assets/logo.svg create mode 100644 playground/typescript-router-playwright/src/assets/main.css create mode 100644 playground/typescript-router-playwright/src/components/HelloWorld.vue create mode 100644 playground/typescript-router-playwright/src/components/TheWelcome.vue create mode 100644 playground/typescript-router-playwright/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router-playwright/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router-playwright/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router-playwright/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router-playwright/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router-playwright/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router-playwright/src/main.ts create mode 100644 playground/typescript-router-playwright/src/router/index.ts create mode 100644 playground/typescript-router-playwright/src/views/AboutView.vue create mode 100644 playground/typescript-router-playwright/src/views/HomeView.vue create mode 100644 playground/typescript-router-playwright/tsconfig.app.json create mode 100644 playground/typescript-router-playwright/tsconfig.json create mode 100644 playground/typescript-router-playwright/tsconfig.node.json create mode 100644 playground/typescript-router-playwright/vite.config.ts create mode 100644 playground/typescript-router-vitest-cypress/.gitignore create mode 100644 playground/typescript-router-vitest-cypress/README.md create mode 100644 playground/typescript-router-vitest-cypress/cypress.config.ts create mode 100644 playground/typescript-router-vitest-cypress/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-router-vitest-cypress/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-router-vitest-cypress/cypress/fixtures/example.json create mode 100644 playground/typescript-router-vitest-cypress/cypress/support/commands.ts create mode 100644 playground/typescript-router-vitest-cypress/cypress/support/e2e.ts create mode 100644 playground/typescript-router-vitest-cypress/env.d.ts create mode 100644 playground/typescript-router-vitest-cypress/index.html create mode 100644 playground/typescript-router-vitest-cypress/package.json create mode 100644 playground/typescript-router-vitest-cypress/public/favicon.ico create mode 100644 playground/typescript-router-vitest-cypress/src/App.vue create mode 100644 playground/typescript-router-vitest-cypress/src/assets/logo.svg create mode 100644 playground/typescript-router-vitest-cypress/src/assets/main.css create mode 100644 playground/typescript-router-vitest-cypress/src/components/HelloWorld.vue create mode 100644 playground/typescript-router-vitest-cypress/src/components/TheWelcome.vue create mode 100644 playground/typescript-router-vitest-cypress/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-router-vitest-cypress/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router-vitest-cypress/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router-vitest-cypress/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router-vitest-cypress/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router-vitest-cypress/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router-vitest-cypress/src/main.ts create mode 100644 playground/typescript-router-vitest-cypress/src/router/index.ts create mode 100644 playground/typescript-router-vitest-cypress/src/views/AboutView.vue create mode 100644 playground/typescript-router-vitest-cypress/src/views/HomeView.vue create mode 100644 playground/typescript-router-vitest-cypress/tsconfig.app.json create mode 100644 playground/typescript-router-vitest-cypress/tsconfig.json create mode 100644 playground/typescript-router-vitest-cypress/tsconfig.node.json create mode 100644 playground/typescript-router-vitest-cypress/tsconfig.vitest.json create mode 100644 playground/typescript-router-vitest-cypress/vite.config.ts create mode 100644 playground/typescript-router-vitest-cypress/vitest.config.ts create mode 100644 playground/typescript-router-vitest-nightwatch/.gitignore create mode 100644 playground/typescript-router-vitest-nightwatch/.vscode/extensions.json create mode 100644 playground/typescript-router-vitest-nightwatch/README.md create mode 100644 playground/typescript-router-vitest-nightwatch/env.d.ts create mode 100644 playground/typescript-router-vitest-nightwatch/index.html create mode 100644 playground/typescript-router-vitest-nightwatch/nightwatch.conf.cjs create mode 100644 playground/typescript-router-vitest-nightwatch/nightwatch/nightwatch.d.ts create mode 100644 playground/typescript-router-vitest-nightwatch/nightwatch/tsconfig.json create mode 100644 playground/typescript-router-vitest-nightwatch/package.json create mode 100644 playground/typescript-router-vitest-nightwatch/public/favicon.ico create mode 100644 playground/typescript-router-vitest-nightwatch/src/App.vue create mode 100644 playground/typescript-router-vitest-nightwatch/src/assets/logo.svg create mode 100644 playground/typescript-router-vitest-nightwatch/src/assets/main.css create mode 100644 playground/typescript-router-vitest-nightwatch/src/components/HelloWorld.vue create mode 100644 playground/typescript-router-vitest-nightwatch/src/components/TheWelcome.vue create mode 100644 playground/typescript-router-vitest-nightwatch/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-router-vitest-nightwatch/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router-vitest-nightwatch/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router-vitest-nightwatch/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router-vitest-nightwatch/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router-vitest-nightwatch/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router-vitest-nightwatch/src/main.ts create mode 100644 playground/typescript-router-vitest-nightwatch/src/router/index.ts create mode 100644 playground/typescript-router-vitest-nightwatch/src/views/AboutView.vue create mode 100644 playground/typescript-router-vitest-nightwatch/src/views/HomeView.vue create mode 100644 playground/typescript-router-vitest-nightwatch/tests/e2e/example.ts create mode 100644 playground/typescript-router-vitest-nightwatch/tsconfig.app.json create mode 100644 playground/typescript-router-vitest-nightwatch/tsconfig.json create mode 100644 playground/typescript-router-vitest-nightwatch/tsconfig.node.json create mode 100644 playground/typescript-router-vitest-nightwatch/tsconfig.vitest.json create mode 100644 playground/typescript-router-vitest-nightwatch/vite.config.ts create mode 100644 playground/typescript-router-vitest-nightwatch/vitest.config.ts create mode 100644 playground/typescript-router-vitest-playwright/.gitignore create mode 100644 playground/typescript-router-vitest-playwright/.vscode/extensions.json create mode 100644 playground/typescript-router-vitest-playwright/README.md create mode 100644 playground/typescript-router-vitest-playwright/e2e/tsconfig.json create mode 100644 playground/typescript-router-vitest-playwright/e2e/vue.spec.ts create mode 100644 playground/typescript-router-vitest-playwright/env.d.ts create mode 100644 playground/typescript-router-vitest-playwright/index.html create mode 100644 playground/typescript-router-vitest-playwright/package.json create mode 100644 playground/typescript-router-vitest-playwright/playwright.config.ts create mode 100644 playground/typescript-router-vitest-playwright/public/favicon.ico create mode 100644 playground/typescript-router-vitest-playwright/src/App.vue create mode 100644 playground/typescript-router-vitest-playwright/src/assets/logo.svg create mode 100644 playground/typescript-router-vitest-playwright/src/assets/main.css create mode 100644 playground/typescript-router-vitest-playwright/src/components/HelloWorld.vue create mode 100644 playground/typescript-router-vitest-playwright/src/components/TheWelcome.vue create mode 100644 playground/typescript-router-vitest-playwright/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-router-vitest-playwright/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router-vitest-playwright/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router-vitest-playwright/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router-vitest-playwright/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router-vitest-playwright/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router-vitest-playwright/src/main.ts create mode 100644 playground/typescript-router-vitest-playwright/src/router/index.ts create mode 100644 playground/typescript-router-vitest-playwright/src/views/AboutView.vue create mode 100644 playground/typescript-router-vitest-playwright/src/views/HomeView.vue create mode 100644 playground/typescript-router-vitest-playwright/tsconfig.app.json create mode 100644 playground/typescript-router-vitest-playwright/tsconfig.json create mode 100644 playground/typescript-router-vitest-playwright/tsconfig.node.json create mode 100644 playground/typescript-router-vitest-playwright/tsconfig.vitest.json create mode 100644 playground/typescript-router-vitest-playwright/vite.config.ts create mode 100644 playground/typescript-router-vitest-playwright/vitest.config.ts create mode 100644 playground/typescript-router-vitest/.gitignore create mode 100644 playground/typescript-router-vitest/README.md create mode 100644 playground/typescript-router-vitest/env.d.ts create mode 100644 playground/typescript-router-vitest/index.html create mode 100644 playground/typescript-router-vitest/package.json create mode 100644 playground/typescript-router-vitest/public/favicon.ico create mode 100644 playground/typescript-router-vitest/src/App.vue create mode 100644 playground/typescript-router-vitest/src/assets/logo.svg create mode 100644 playground/typescript-router-vitest/src/assets/main.css create mode 100644 playground/typescript-router-vitest/src/components/HelloWorld.vue create mode 100644 playground/typescript-router-vitest/src/components/TheWelcome.vue create mode 100644 playground/typescript-router-vitest/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router-vitest/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-router-vitest/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router-vitest/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router-vitest/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router-vitest/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router-vitest/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router-vitest/src/main.ts create mode 100644 playground/typescript-router-vitest/src/router/index.ts create mode 100644 playground/typescript-router-vitest/src/views/AboutView.vue create mode 100644 playground/typescript-router-vitest/src/views/HomeView.vue create mode 100644 playground/typescript-router-vitest/tsconfig.app.json create mode 100644 playground/typescript-router-vitest/tsconfig.json create mode 100644 playground/typescript-router-vitest/tsconfig.node.json create mode 100644 playground/typescript-router-vitest/tsconfig.vitest.json create mode 100644 playground/typescript-router-vitest/vite.config.ts create mode 100644 playground/typescript-router-vitest/vitest.config.ts create mode 100644 playground/typescript-router-with-tests/.gitignore create mode 100644 playground/typescript-router-with-tests/README.md create mode 100644 playground/typescript-router-with-tests/cypress.config.ts create mode 100644 playground/typescript-router-with-tests/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-router-with-tests/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-router-with-tests/cypress/fixtures/example.json create mode 100644 playground/typescript-router-with-tests/cypress/support/commands.ts create mode 100644 playground/typescript-router-with-tests/cypress/support/e2e.ts create mode 100644 playground/typescript-router-with-tests/env.d.ts create mode 100644 playground/typescript-router-with-tests/index.html create mode 100644 playground/typescript-router-with-tests/package.json create mode 100644 playground/typescript-router-with-tests/public/favicon.ico create mode 100644 playground/typescript-router-with-tests/src/App.vue create mode 100644 playground/typescript-router-with-tests/src/assets/logo.svg create mode 100644 playground/typescript-router-with-tests/src/assets/main.css create mode 100644 playground/typescript-router-with-tests/src/components/HelloWorld.vue create mode 100644 playground/typescript-router-with-tests/src/components/TheWelcome.vue create mode 100644 playground/typescript-router-with-tests/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router-with-tests/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-router-with-tests/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router-with-tests/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router-with-tests/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router-with-tests/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router-with-tests/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router-with-tests/src/main.ts create mode 100644 playground/typescript-router-with-tests/src/router/index.ts create mode 100644 playground/typescript-router-with-tests/src/views/AboutView.vue create mode 100644 playground/typescript-router-with-tests/src/views/HomeView.vue create mode 100644 playground/typescript-router-with-tests/tsconfig.app.json create mode 100644 playground/typescript-router-with-tests/tsconfig.json create mode 100644 playground/typescript-router-with-tests/tsconfig.node.json create mode 100644 playground/typescript-router-with-tests/tsconfig.vitest.json create mode 100644 playground/typescript-router-with-tests/vite.config.ts create mode 100644 playground/typescript-router-with-tests/vitest.config.ts create mode 100644 playground/typescript-router/.gitignore create mode 100644 playground/typescript-router/README.md create mode 100644 playground/typescript-router/env.d.ts create mode 100644 playground/typescript-router/index.html create mode 100644 playground/typescript-router/package.json create mode 100644 playground/typescript-router/public/favicon.ico create mode 100644 playground/typescript-router/src/App.vue create mode 100644 playground/typescript-router/src/assets/logo.svg create mode 100644 playground/typescript-router/src/assets/main.css create mode 100644 playground/typescript-router/src/components/HelloWorld.vue create mode 100644 playground/typescript-router/src/components/TheWelcome.vue create mode 100644 playground/typescript-router/src/components/WelcomeItem.vue create mode 100644 playground/typescript-router/src/components/icons/IconCommunity.vue create mode 100644 playground/typescript-router/src/components/icons/IconDocumentation.vue create mode 100644 playground/typescript-router/src/components/icons/IconEcosystem.vue create mode 100644 playground/typescript-router/src/components/icons/IconSupport.vue create mode 100644 playground/typescript-router/src/components/icons/IconTooling.vue create mode 100644 playground/typescript-router/src/main.ts create mode 100644 playground/typescript-router/src/router/index.ts create mode 100644 playground/typescript-router/src/views/AboutView.vue create mode 100644 playground/typescript-router/src/views/HomeView.vue create mode 100644 playground/typescript-router/tsconfig.app.json create mode 100644 playground/typescript-router/tsconfig.json create mode 100644 playground/typescript-router/tsconfig.node.json create mode 100644 playground/typescript-router/vite.config.ts create mode 100644 playground/typescript-vitest-cypress/.gitignore create mode 100644 playground/typescript-vitest-cypress/README.md create mode 100644 playground/typescript-vitest-cypress/cypress.config.ts create mode 100644 playground/typescript-vitest-cypress/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-vitest-cypress/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-vitest-cypress/cypress/fixtures/example.json create mode 100644 playground/typescript-vitest-cypress/cypress/support/commands.ts create mode 100644 playground/typescript-vitest-cypress/cypress/support/e2e.ts create mode 100644 playground/typescript-vitest-cypress/env.d.ts create mode 100644 playground/typescript-vitest-cypress/index.html create mode 100644 playground/typescript-vitest-cypress/package.json create mode 100644 playground/typescript-vitest-cypress/public/favicon.ico create mode 100644 playground/typescript-vitest-cypress/src/App.vue create mode 100644 playground/typescript-vitest-cypress/src/assets/logo.svg create mode 100644 playground/typescript-vitest-cypress/src/assets/main.css create mode 100644 playground/typescript-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-vitest-cypress/src/main.ts create mode 100644 playground/typescript-vitest-cypress/tsconfig.app.json create mode 100644 playground/typescript-vitest-cypress/tsconfig.json create mode 100644 playground/typescript-vitest-cypress/tsconfig.node.json create mode 100644 playground/typescript-vitest-cypress/tsconfig.vitest.json create mode 100644 playground/typescript-vitest-cypress/vite.config.ts create mode 100644 playground/typescript-vitest-cypress/vitest.config.ts create mode 100644 playground/typescript-vitest-nightwatch/.gitignore create mode 100644 playground/typescript-vitest-nightwatch/.vscode/extensions.json create mode 100644 playground/typescript-vitest-nightwatch/README.md create mode 100644 playground/typescript-vitest-nightwatch/env.d.ts create mode 100644 playground/typescript-vitest-nightwatch/index.html create mode 100644 playground/typescript-vitest-nightwatch/nightwatch.conf.cjs create mode 100644 playground/typescript-vitest-nightwatch/nightwatch/nightwatch.d.ts create mode 100644 playground/typescript-vitest-nightwatch/nightwatch/tsconfig.json create mode 100644 playground/typescript-vitest-nightwatch/package.json create mode 100644 playground/typescript-vitest-nightwatch/public/favicon.ico create mode 100644 playground/typescript-vitest-nightwatch/src/App.vue create mode 100644 playground/typescript-vitest-nightwatch/src/assets/logo.svg create mode 100644 playground/typescript-vitest-nightwatch/src/assets/main.css create mode 100644 playground/typescript-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-vitest-nightwatch/src/main.ts create mode 100644 playground/typescript-vitest-nightwatch/tests/e2e/example.ts create mode 100644 playground/typescript-vitest-nightwatch/tsconfig.app.json create mode 100644 playground/typescript-vitest-nightwatch/tsconfig.json create mode 100644 playground/typescript-vitest-nightwatch/tsconfig.node.json create mode 100644 playground/typescript-vitest-nightwatch/tsconfig.vitest.json create mode 100644 playground/typescript-vitest-nightwatch/vite.config.ts create mode 100644 playground/typescript-vitest-nightwatch/vitest.config.ts create mode 100644 playground/typescript-vitest-playwright/.gitignore create mode 100644 playground/typescript-vitest-playwright/.vscode/extensions.json create mode 100644 playground/typescript-vitest-playwright/README.md create mode 100644 playground/typescript-vitest-playwright/e2e/tsconfig.json create mode 100644 playground/typescript-vitest-playwright/e2e/vue.spec.ts create mode 100644 playground/typescript-vitest-playwright/env.d.ts create mode 100644 playground/typescript-vitest-playwright/index.html create mode 100644 playground/typescript-vitest-playwright/package.json create mode 100644 playground/typescript-vitest-playwright/playwright.config.ts create mode 100644 playground/typescript-vitest-playwright/public/favicon.ico create mode 100644 playground/typescript-vitest-playwright/src/App.vue create mode 100644 playground/typescript-vitest-playwright/src/assets/logo.svg create mode 100644 playground/typescript-vitest-playwright/src/assets/main.css create mode 100644 playground/typescript-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-vitest-playwright/src/main.ts create mode 100644 playground/typescript-vitest-playwright/tsconfig.app.json create mode 100644 playground/typescript-vitest-playwright/tsconfig.json create mode 100644 playground/typescript-vitest-playwright/tsconfig.node.json create mode 100644 playground/typescript-vitest-playwright/tsconfig.vitest.json create mode 100644 playground/typescript-vitest-playwright/vite.config.ts create mode 100644 playground/typescript-vitest-playwright/vitest.config.ts create mode 100644 playground/typescript-vitest/.gitignore create mode 100644 playground/typescript-vitest/README.md create mode 100644 playground/typescript-vitest/env.d.ts create mode 100644 playground/typescript-vitest/index.html create mode 100644 playground/typescript-vitest/package.json create mode 100644 playground/typescript-vitest/public/favicon.ico create mode 100644 playground/typescript-vitest/src/App.vue create mode 100644 playground/typescript-vitest/src/assets/logo.svg create mode 100644 playground/typescript-vitest/src/assets/main.css create mode 100644 playground/typescript-vitest/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-vitest/src/main.ts create mode 100644 playground/typescript-vitest/tsconfig.app.json create mode 100644 playground/typescript-vitest/tsconfig.json create mode 100644 playground/typescript-vitest/tsconfig.node.json create mode 100644 playground/typescript-vitest/tsconfig.vitest.json create mode 100644 playground/typescript-vitest/vite.config.ts create mode 100644 playground/typescript-vitest/vitest.config.ts create mode 100644 playground/typescript-with-tests/.gitignore create mode 100644 playground/typescript-with-tests/README.md create mode 100644 playground/typescript-with-tests/cypress.config.ts create mode 100644 playground/typescript-with-tests/cypress/e2e/example.cy.ts create mode 100644 playground/typescript-with-tests/cypress/e2e/tsconfig.json create mode 100644 playground/typescript-with-tests/cypress/fixtures/example.json create mode 100644 playground/typescript-with-tests/cypress/support/commands.ts create mode 100644 playground/typescript-with-tests/cypress/support/e2e.ts create mode 100644 playground/typescript-with-tests/env.d.ts create mode 100644 playground/typescript-with-tests/index.html create mode 100644 playground/typescript-with-tests/package.json create mode 100644 playground/typescript-with-tests/public/favicon.ico create mode 100644 playground/typescript-with-tests/src/App.vue create mode 100644 playground/typescript-with-tests/src/assets/logo.svg create mode 100644 playground/typescript-with-tests/src/assets/main.css create mode 100644 playground/typescript-with-tests/src/components/__tests__/HelloWorld.spec.ts create mode 100644 playground/typescript-with-tests/src/main.ts create mode 100644 playground/typescript-with-tests/tsconfig.app.json create mode 100644 playground/typescript-with-tests/tsconfig.json create mode 100644 playground/typescript-with-tests/tsconfig.node.json create mode 100644 playground/typescript-with-tests/tsconfig.vitest.json create mode 100644 playground/typescript-with-tests/vite.config.ts create mode 100644 playground/typescript-with-tests/vitest.config.ts create mode 100644 playground/typescript/.gitignore create mode 100644 playground/typescript/README.md create mode 100644 playground/typescript/env.d.ts create mode 100644 playground/typescript/index.html create mode 100644 playground/typescript/package.json create mode 100644 playground/typescript/public/favicon.ico create mode 100644 playground/typescript/src/App.vue create mode 100644 playground/typescript/src/assets/logo.svg create mode 100644 playground/typescript/src/assets/main.css create mode 100644 playground/typescript/src/main.ts create mode 100644 playground/typescript/tsconfig.app.json create mode 100644 playground/typescript/tsconfig.json create mode 100644 playground/typescript/tsconfig.node.json create mode 100644 playground/typescript/vite.config.ts create mode 100644 playground/vitest-cypress/.gitignore create mode 100644 playground/vitest-cypress/README.md create mode 100644 playground/vitest-cypress/cypress.config.js create mode 100644 playground/vitest-cypress/cypress/e2e/example.cy.js create mode 100644 playground/vitest-cypress/cypress/e2e/jsconfig.json create mode 100644 playground/vitest-cypress/cypress/fixtures/example.json create mode 100644 playground/vitest-cypress/cypress/support/commands.js create mode 100644 playground/vitest-cypress/cypress/support/e2e.js create mode 100644 playground/vitest-cypress/index.html create mode 100644 playground/vitest-cypress/jsconfig.json create mode 100644 playground/vitest-cypress/package.json create mode 100644 playground/vitest-cypress/public/favicon.ico create mode 100644 playground/vitest-cypress/src/App.vue create mode 100644 playground/vitest-cypress/src/assets/logo.svg create mode 100644 playground/vitest-cypress/src/assets/main.css create mode 100644 playground/vitest-cypress/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/vitest-cypress/src/main.js create mode 100644 playground/vitest-cypress/vite.config.js create mode 100644 playground/vitest-cypress/vitest.config.js create mode 100644 playground/vitest-nightwatch/.gitignore create mode 100644 playground/vitest-nightwatch/.vscode/extensions.json create mode 100644 playground/vitest-nightwatch/README.md create mode 100644 playground/vitest-nightwatch/index.html create mode 100644 playground/vitest-nightwatch/jsconfig.json create mode 100644 playground/vitest-nightwatch/nightwatch.conf.cjs create mode 100644 playground/vitest-nightwatch/package.json create mode 100644 playground/vitest-nightwatch/public/favicon.ico create mode 100644 playground/vitest-nightwatch/src/App.vue create mode 100644 playground/vitest-nightwatch/src/assets/logo.svg create mode 100644 playground/vitest-nightwatch/src/assets/main.css create mode 100644 playground/vitest-nightwatch/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/vitest-nightwatch/src/main.js create mode 100644 playground/vitest-nightwatch/tests/e2e/example.js create mode 100644 playground/vitest-nightwatch/vite.config.js create mode 100644 playground/vitest-nightwatch/vitest.config.js create mode 100644 playground/vitest-playwright/.gitignore create mode 100644 playground/vitest-playwright/.vscode/extensions.json create mode 100644 playground/vitest-playwright/README.md create mode 100644 playground/vitest-playwright/e2e/vue.spec.js create mode 100644 playground/vitest-playwright/index.html create mode 100644 playground/vitest-playwright/jsconfig.json create mode 100644 playground/vitest-playwright/package.json create mode 100644 playground/vitest-playwright/playwright.config.js create mode 100644 playground/vitest-playwright/public/favicon.ico create mode 100644 playground/vitest-playwright/src/App.vue create mode 100644 playground/vitest-playwright/src/assets/logo.svg create mode 100644 playground/vitest-playwright/src/assets/main.css create mode 100644 playground/vitest-playwright/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/vitest-playwright/src/main.js create mode 100644 playground/vitest-playwright/vite.config.js create mode 100644 playground/vitest-playwright/vitest.config.js create mode 100644 playground/vitest/.gitignore create mode 100644 playground/vitest/README.md create mode 100644 playground/vitest/index.html create mode 100644 playground/vitest/jsconfig.json create mode 100644 playground/vitest/package.json create mode 100644 playground/vitest/public/favicon.ico create mode 100644 playground/vitest/src/App.vue create mode 100644 playground/vitest/src/assets/logo.svg create mode 100644 playground/vitest/src/assets/main.css create mode 100644 playground/vitest/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/vitest/src/main.js create mode 100644 playground/vitest/vite.config.js create mode 100644 playground/vitest/vitest.config.js create mode 100644 playground/with-tests/.gitignore create mode 100644 playground/with-tests/README.md create mode 100644 playground/with-tests/cypress.config.js create mode 100644 playground/with-tests/cypress/e2e/example.cy.js create mode 100644 playground/with-tests/cypress/e2e/jsconfig.json create mode 100644 playground/with-tests/cypress/fixtures/example.json create mode 100644 playground/with-tests/cypress/support/commands.js create mode 100644 playground/with-tests/cypress/support/e2e.js create mode 100644 playground/with-tests/index.html create mode 100644 playground/with-tests/jsconfig.json create mode 100644 playground/with-tests/package.json create mode 100644 playground/with-tests/public/favicon.ico create mode 100644 playground/with-tests/src/App.vue create mode 100644 playground/with-tests/src/assets/logo.svg create mode 100644 playground/with-tests/src/assets/main.css create mode 100644 playground/with-tests/src/components/__tests__/HelloWorld.spec.js create mode 100644 playground/with-tests/src/main.js create mode 100644 playground/with-tests/vite.config.js create mode 100644 playground/with-tests/vitest.config.js create mode 100644 scripts/LICENSE create mode 100644 template/base/.eslintignore create mode 100644 template/base/.eslintrc.cjs create mode 100644 template/base/.gitignore create mode 100644 template/base/.prettierrc.json create mode 100644 template/base/public/config.js create mode 100644 template/base/src/api/apiIndex.js create mode 100644 template/base/src/api/apisTest.js create mode 100644 template/base/src/config/configIndex.js create mode 100644 template/base/src/libs/custom_axios.js create mode 100644 template/code/typescript-router/src/views/Home.vue diff --git a/.gitignore b/.gitignore index f7999996c..5d963203d 100644 --- a/.gitignore +++ b/.gitignore @@ -106,3 +106,5 @@ dist # TernJS port file .tern-port +/node_modules/ +/.idea/ diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 000000000..b58b603fe --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/create-vue-customized.iml b/.idea/create-vue-customized.iml new file mode 100644 index 000000000..0c8867d7e --- /dev/null +++ b/.idea/create-vue-customized.iml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/markdown.xml b/.idea/markdown.xml new file mode 100644 index 000000000..1e3409412 --- /dev/null +++ b/.idea/markdown.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 000000000..fb26bc159 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..94a25f7f4 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/media/screenshot-cli.png b/media/screenshot-cli.png index e81d6cb18745de88f82f47708f0d1eb78e8202b0..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 GIT binary patch literal 0 HcmV?d00001 literal 432497 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

i*=_!#*nF+KC&Q320LG>B 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⁡= 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%0DnLE&}@2~bUKJTd>0 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

@jI?u<$7rJ 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 { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/pinia-cypress/cypress/e2e/jsconfig.json b/playground/pinia-cypress/cypress/e2e/jsconfig.json new file mode 100644 index 000000000..c790a70d6 --- /dev/null +++ b/playground/pinia-cypress/cypress/e2e/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + }, + "include": ["./**/*", "../support/**/*"] +} diff --git a/playground/pinia-cypress/cypress/fixtures/example.json b/playground/pinia-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/pinia-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/pinia-cypress/cypress/support/commands.js b/playground/pinia-cypress/cypress/support/commands.js new file mode 100644 index 000000000..119ab03f7 --- /dev/null +++ b/playground/pinia-cypress/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) diff --git a/playground/pinia-cypress/cypress/support/component-index.html b/playground/pinia-cypress/cypress/support/component-index.html new file mode 100644 index 000000000..5f9622ae2 --- /dev/null +++ b/playground/pinia-cypress/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + Components App + + +

+ + diff --git a/playground/pinia-cypress/cypress/support/component.js b/playground/pinia-cypress/cypress/support/component.js new file mode 100644 index 000000000..7283cad6d --- /dev/null +++ b/playground/pinia-cypress/cypress/support/component.js @@ -0,0 +1,30 @@ +// *********************************************************** +// This example support/component.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') + +// Import global styles +import '@/assets/main.css' + +import { mount } from 'cypress/vue' + +Cypress.Commands.add('mount', mount) + +// Example use: +// cy.mount(MyComponent) diff --git a/playground/pinia-cypress/cypress/support/e2e.js b/playground/pinia-cypress/cypress/support/e2e.js new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/pinia-cypress/cypress/support/e2e.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/pinia-cypress/index.html b/playground/pinia-cypress/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/pinia-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/pinia-cypress/jsconfig.json b/playground/pinia-cypress/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/pinia-cypress/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/pinia-cypress/package.json b/playground/pinia-cypress/package.json new file mode 100644 index 000000000..05c4f04d0 --- /dev/null +++ b/playground/pinia-cypress/package.json @@ -0,0 +1,25 @@ +{ + "name": "pinia-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "test:unit": "cypress run --component", + "test:unit:dev": "cypress open --component" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "cypress": "^13.6.4", + "start-server-and-test": "^2.0.3", + "vite": "^5.0.11" + } +} diff --git a/playground/pinia-cypress/public/favicon.ico b/playground/pinia-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/pinia-cypress/src/App.vue b/playground/pinia-cypress/src/App.vue new file mode 100644 index 000000000..b6f965e35 --- /dev/null +++ b/playground/pinia-cypress/src/App.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/playground/pinia-cypress/src/assets/logo.svg b/playground/pinia-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/pinia-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/pinia-cypress/src/assets/main.css b/playground/pinia-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/pinia-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/pinia-cypress/src/components/__tests__/HelloWorld.cy.js b/playground/pinia-cypress/src/components/__tests__/HelloWorld.cy.js new file mode 100644 index 000000000..535a0e51c --- /dev/null +++ b/playground/pinia-cypress/src/components/__tests__/HelloWorld.cy.js @@ -0,0 +1,12 @@ +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('playground', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + }) + + it('renders properly', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + cy.get('h1').should('contain', 'Hello Cypress') + }) +}) diff --git a/playground/pinia-cypress/src/main.js b/playground/pinia-cypress/src/main.js new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/pinia-cypress/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/pinia-cypress/src/stores/counter.js b/playground/pinia-cypress/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/pinia-cypress/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/pinia-cypress/vite.config.js b/playground/pinia-cypress/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/pinia-cypress/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/pinia-nightwatch/.gitignore b/playground/pinia-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/pinia-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/pinia-nightwatch/.vscode/extensions.json b/playground/pinia-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/pinia-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/pinia-nightwatch/README.md b/playground/pinia-nightwatch/README.md new file mode 100644 index 000000000..cd3747bc2 --- /dev/null +++ b/playground/pinia-nightwatch/README.md @@ -0,0 +1,52 @@ +# pinia-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.js +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/pinia-nightwatch/index.html b/playground/pinia-nightwatch/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/pinia-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/pinia-nightwatch/jsconfig.json b/playground/pinia-nightwatch/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/pinia-nightwatch/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/pinia-nightwatch/nightwatch.conf.cjs b/playground/pinia-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/pinia-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/pinia-nightwatch/nightwatch/index.html b/playground/pinia-nightwatch/nightwatch/index.html new file mode 100644 index 000000000..b7e1ec765 --- /dev/null +++ b/playground/pinia-nightwatch/nightwatch/index.html @@ -0,0 +1,16 @@ + + + + + + + + + Vue Renderer + + + +
+ + + diff --git a/playground/pinia-nightwatch/package.json b/playground/pinia-nightwatch/package.json new file mode 100644 index 000000000..8628cf9bd --- /dev/null +++ b/playground/pinia-nightwatch/package.json @@ -0,0 +1,28 @@ +{ + "name": "pinia-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:e2e": "nightwatch tests/e2e/*", + "test:unit": "nightwatch src/**/__tests__/*" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "nightwatch": "^3.4.0", + "ts-node": "^10.9.2", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6" + } +} diff --git a/playground/pinia-nightwatch/public/favicon.ico b/playground/pinia-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/pinia-nightwatch/src/App.vue b/playground/pinia-nightwatch/src/App.vue new file mode 100644 index 000000000..b6f965e35 --- /dev/null +++ b/playground/pinia-nightwatch/src/App.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/playground/pinia-nightwatch/src/assets/logo.svg b/playground/pinia-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/pinia-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/pinia-nightwatch/src/assets/main.css b/playground/pinia-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/pinia-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/pinia-nightwatch/src/components/__tests__/HelloWorld.spec.js b/playground/pinia-nightwatch/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..810641e6e --- /dev/null +++ b/playground/pinia-nightwatch/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,14 @@ +describe('Hello World', function () { + before((browser) => { + browser.init() + }) + + it('renders properly', async function () { + const welcomeComponent = await browser.mountComponent('/src/components/HelloWorld.vue', {props: {msg: 'Hello Nightwatch'}}); + + browser.expect.element(welcomeComponent).to.be.present; + browser.expect.element('h1').text.to.contain('Hello Nightwatch'); + }) + + after((browser) => browser.end()) +}) diff --git a/playground/pinia-nightwatch/src/main.js b/playground/pinia-nightwatch/src/main.js new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/pinia-nightwatch/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/pinia-nightwatch/src/stores/counter.js b/playground/pinia-nightwatch/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/pinia-nightwatch/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/pinia-nightwatch/tests/e2e/example.js b/playground/pinia-nightwatch/tests/e2e/example.js new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/pinia-nightwatch/tests/e2e/example.js @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/pinia-nightwatch/vite.config.js b/playground/pinia-nightwatch/vite.config.js new file mode 100644 index 000000000..fd83c5b21 --- /dev/null +++ b/playground/pinia-nightwatch/vite.config.js @@ -0,0 +1,20 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + nightwatchPlugin({ + renderPage: './nightwatch/index.html' + }), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/pinia-playwright/.gitignore b/playground/pinia-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/pinia-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/pinia-playwright/.vscode/extensions.json b/playground/pinia-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/pinia-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/pinia-playwright/README.md b/playground/pinia-playwright/README.md new file mode 100644 index 000000000..25c7aee92 --- /dev/null +++ b/playground/pinia-playwright/README.md @@ -0,0 +1,48 @@ +# pinia-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/pinia-playwright/e2e/vue.spec.js b/playground/pinia-playwright/e2e/vue.spec.js new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/pinia-playwright/e2e/vue.spec.js @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/pinia-playwright/index.html b/playground/pinia-playwright/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/pinia-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/pinia-playwright/jsconfig.json b/playground/pinia-playwright/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/pinia-playwright/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/pinia-playwright/package.json b/playground/pinia-playwright/package.json new file mode 100644 index 000000000..2d3590ec3 --- /dev/null +++ b/playground/pinia-playwright/package.json @@ -0,0 +1,21 @@ +{ + "name": "pinia-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:e2e": "playwright test" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@vitejs/plugin-vue": "^5.0.3", + "vite": "^5.0.11" + } +} diff --git a/playground/pinia-playwright/playwright.config.js b/playground/pinia-playwright/playwright.config.js new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/pinia-playwright/playwright.config.js @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/pinia-playwright/public/favicon.ico b/playground/pinia-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/pinia-playwright/src/App.vue b/playground/pinia-playwright/src/App.vue new file mode 100644 index 000000000..b6f965e35 --- /dev/null +++ b/playground/pinia-playwright/src/App.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/playground/pinia-playwright/src/assets/logo.svg b/playground/pinia-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/pinia-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/pinia-playwright/src/assets/main.css b/playground/pinia-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/pinia-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/pinia-playwright/src/main.js b/playground/pinia-playwright/src/main.js new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/pinia-playwright/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/pinia-playwright/src/stores/counter.js b/playground/pinia-playwright/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/pinia-playwright/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/pinia-playwright/vite.config.js b/playground/pinia-playwright/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/pinia-playwright/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/pinia-vitest-cypress/.gitignore b/playground/pinia-vitest-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/pinia-vitest-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/pinia-vitest-cypress/README.md b/playground/pinia-vitest-cypress/README.md new file mode 100644 index 000000000..01c890d9d --- /dev/null +++ b/playground/pinia-vitest-cypress/README.md @@ -0,0 +1,51 @@ +# pinia-vitest-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/pinia-vitest-cypress/cypress.config.js b/playground/pinia-vitest-cypress/cypress.config.js new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/pinia-vitest-cypress/cypress.config.js @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/pinia-vitest-cypress/cypress/e2e/example.cy.js b/playground/pinia-vitest-cypress/cypress/e2e/example.cy.js new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/pinia-vitest-cypress/cypress/e2e/example.cy.js @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/pinia-vitest-cypress/cypress/e2e/jsconfig.json b/playground/pinia-vitest-cypress/cypress/e2e/jsconfig.json new file mode 100644 index 000000000..c790a70d6 --- /dev/null +++ b/playground/pinia-vitest-cypress/cypress/e2e/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + }, + "include": ["./**/*", "../support/**/*"] +} diff --git a/playground/pinia-vitest-cypress/cypress/fixtures/example.json b/playground/pinia-vitest-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/pinia-vitest-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/pinia-vitest-cypress/cypress/support/commands.js b/playground/pinia-vitest-cypress/cypress/support/commands.js new file mode 100644 index 000000000..119ab03f7 --- /dev/null +++ b/playground/pinia-vitest-cypress/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) diff --git a/playground/pinia-vitest-cypress/cypress/support/e2e.js b/playground/pinia-vitest-cypress/cypress/support/e2e.js new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/pinia-vitest-cypress/cypress/support/e2e.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/pinia-vitest-cypress/index.html b/playground/pinia-vitest-cypress/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/pinia-vitest-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/pinia-vitest-cypress/jsconfig.json b/playground/pinia-vitest-cypress/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/pinia-vitest-cypress/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/pinia-vitest-cypress/package.json b/playground/pinia-vitest-cypress/package.json new file mode 100644 index 000000000..eccd2a7bb --- /dev/null +++ b/playground/pinia-vitest-cypress/package.json @@ -0,0 +1,27 @@ +{ + "name": "pinia-vitest-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "start-server-and-test": "^2.0.3", + "vite": "^5.0.11", + "vitest": "^1.2.2" + } +} diff --git a/playground/pinia-vitest-cypress/public/favicon.ico b/playground/pinia-vitest-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/pinia-vitest-cypress/src/App.vue b/playground/pinia-vitest-cypress/src/App.vue new file mode 100644 index 000000000..b6f965e35 --- /dev/null +++ b/playground/pinia-vitest-cypress/src/App.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/playground/pinia-vitest-cypress/src/assets/logo.svg b/playground/pinia-vitest-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/pinia-vitest-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/pinia-vitest-cypress/src/assets/main.css b/playground/pinia-vitest-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/pinia-vitest-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.js b/playground/pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/pinia-vitest-cypress/src/main.js b/playground/pinia-vitest-cypress/src/main.js new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/pinia-vitest-cypress/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/pinia-vitest-cypress/src/stores/counter.js b/playground/pinia-vitest-cypress/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/pinia-vitest-cypress/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/pinia-vitest-cypress/vite.config.js b/playground/pinia-vitest-cypress/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/pinia-vitest-cypress/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/pinia-vitest-cypress/vitest.config.js b/playground/pinia-vitest-cypress/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/pinia-vitest-cypress/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/pinia-vitest-nightwatch/.gitignore b/playground/pinia-vitest-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/pinia-vitest-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/pinia-vitest-nightwatch/.vscode/extensions.json b/playground/pinia-vitest-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/pinia-vitest-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/pinia-vitest-nightwatch/README.md b/playground/pinia-vitest-nightwatch/README.md new file mode 100644 index 000000000..b07896527 --- /dev/null +++ b/playground/pinia-vitest-nightwatch/README.md @@ -0,0 +1,58 @@ +# pinia-vitest-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.js +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/pinia-vitest-nightwatch/index.html b/playground/pinia-vitest-nightwatch/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/pinia-vitest-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/pinia-vitest-nightwatch/jsconfig.json b/playground/pinia-vitest-nightwatch/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/pinia-vitest-nightwatch/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/pinia-vitest-nightwatch/nightwatch.conf.cjs b/playground/pinia-vitest-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/pinia-vitest-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/pinia-vitest-nightwatch/package.json b/playground/pinia-vitest-nightwatch/package.json new file mode 100644 index 000000000..6833ca9c8 --- /dev/null +++ b/playground/pinia-vitest-nightwatch/package.json @@ -0,0 +1,30 @@ +{ + "name": "pinia-vitest-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "nightwatch tests/e2e/*" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "jsdom": "^24.0.0", + "nightwatch": "^3.4.0", + "ts-node": "^10.9.2", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vitest": "^1.2.2" + } +} diff --git a/playground/pinia-vitest-nightwatch/public/favicon.ico b/playground/pinia-vitest-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/pinia-vitest-nightwatch/src/App.vue b/playground/pinia-vitest-nightwatch/src/App.vue new file mode 100644 index 000000000..b6f965e35 --- /dev/null +++ b/playground/pinia-vitest-nightwatch/src/App.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/playground/pinia-vitest-nightwatch/src/assets/logo.svg b/playground/pinia-vitest-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/pinia-vitest-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/pinia-vitest-nightwatch/src/assets/main.css b/playground/pinia-vitest-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/pinia-vitest-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.js b/playground/pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/pinia-vitest-nightwatch/src/main.js b/playground/pinia-vitest-nightwatch/src/main.js new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/pinia-vitest-nightwatch/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/pinia-vitest-nightwatch/src/stores/counter.js b/playground/pinia-vitest-nightwatch/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/pinia-vitest-nightwatch/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/pinia-vitest-nightwatch/tests/e2e/example.js b/playground/pinia-vitest-nightwatch/tests/e2e/example.js new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/pinia-vitest-nightwatch/tests/e2e/example.js @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/pinia-vitest-nightwatch/vite.config.js b/playground/pinia-vitest-nightwatch/vite.config.js new file mode 100644 index 000000000..be3cb9c57 --- /dev/null +++ b/playground/pinia-vitest-nightwatch/vite.config.js @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + nightwatchPlugin(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/pinia-vitest-nightwatch/vitest.config.js b/playground/pinia-vitest-nightwatch/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/pinia-vitest-nightwatch/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/pinia-vitest-playwright/.gitignore b/playground/pinia-vitest-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/pinia-vitest-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/pinia-vitest-playwright/.vscode/extensions.json b/playground/pinia-vitest-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/pinia-vitest-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/pinia-vitest-playwright/README.md b/playground/pinia-vitest-playwright/README.md new file mode 100644 index 000000000..18670b1cb --- /dev/null +++ b/playground/pinia-vitest-playwright/README.md @@ -0,0 +1,54 @@ +# pinia-vitest-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/pinia-vitest-playwright/e2e/vue.spec.js b/playground/pinia-vitest-playwright/e2e/vue.spec.js new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/pinia-vitest-playwright/e2e/vue.spec.js @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/pinia-vitest-playwright/index.html b/playground/pinia-vitest-playwright/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/pinia-vitest-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/pinia-vitest-playwright/jsconfig.json b/playground/pinia-vitest-playwright/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/pinia-vitest-playwright/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/pinia-vitest-playwright/package.json b/playground/pinia-vitest-playwright/package.json new file mode 100644 index 000000000..1ad86a56f --- /dev/null +++ b/playground/pinia-vitest-playwright/package.json @@ -0,0 +1,25 @@ +{ + "name": "pinia-vitest-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "playwright test" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "jsdom": "^24.0.0", + "vite": "^5.0.11", + "vitest": "^1.2.2" + } +} diff --git a/playground/pinia-vitest-playwright/playwright.config.js b/playground/pinia-vitest-playwright/playwright.config.js new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/pinia-vitest-playwright/playwright.config.js @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/pinia-vitest-playwright/public/favicon.ico b/playground/pinia-vitest-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/pinia-vitest-playwright/src/App.vue b/playground/pinia-vitest-playwright/src/App.vue new file mode 100644 index 000000000..b6f965e35 --- /dev/null +++ b/playground/pinia-vitest-playwright/src/App.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/playground/pinia-vitest-playwright/src/assets/logo.svg b/playground/pinia-vitest-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/pinia-vitest-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/pinia-vitest-playwright/src/assets/main.css b/playground/pinia-vitest-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/pinia-vitest-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.js b/playground/pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/pinia-vitest-playwright/src/main.js b/playground/pinia-vitest-playwright/src/main.js new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/pinia-vitest-playwright/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/pinia-vitest-playwright/src/stores/counter.js b/playground/pinia-vitest-playwright/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/pinia-vitest-playwright/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/pinia-vitest-playwright/vite.config.js b/playground/pinia-vitest-playwright/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/pinia-vitest-playwright/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/pinia-vitest-playwright/vitest.config.js b/playground/pinia-vitest-playwright/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/pinia-vitest-playwright/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/pinia-vitest/.gitignore b/playground/pinia-vitest/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/pinia-vitest/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/pinia-vitest/README.md b/playground/pinia-vitest/README.md new file mode 100644 index 000000000..366e7cd1a --- /dev/null +++ b/playground/pinia-vitest/README.md @@ -0,0 +1,35 @@ +# pinia-vitest + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` diff --git a/playground/pinia-vitest/index.html b/playground/pinia-vitest/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/pinia-vitest/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/pinia-vitest/jsconfig.json b/playground/pinia-vitest/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/pinia-vitest/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/pinia-vitest/package.json b/playground/pinia-vitest/package.json new file mode 100644 index 000000000..6ce40d43e --- /dev/null +++ b/playground/pinia-vitest/package.json @@ -0,0 +1,23 @@ +{ + "name": "pinia-vitest", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "jsdom": "^24.0.0", + "vite": "^5.0.11", + "vitest": "^1.2.2" + } +} diff --git a/playground/pinia-vitest/public/favicon.ico b/playground/pinia-vitest/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/pinia-vitest/src/App.vue b/playground/pinia-vitest/src/App.vue new file mode 100644 index 000000000..b6f965e35 --- /dev/null +++ b/playground/pinia-vitest/src/App.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/playground/pinia-vitest/src/assets/logo.svg b/playground/pinia-vitest/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/pinia-vitest/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/pinia-vitest/src/assets/main.css b/playground/pinia-vitest/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/pinia-vitest/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/pinia-vitest/src/components/__tests__/HelloWorld.spec.js b/playground/pinia-vitest/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/pinia-vitest/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/pinia-vitest/src/main.js b/playground/pinia-vitest/src/main.js new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/pinia-vitest/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/pinia-vitest/src/stores/counter.js b/playground/pinia-vitest/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/pinia-vitest/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/pinia-vitest/vite.config.js b/playground/pinia-vitest/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/pinia-vitest/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/pinia-vitest/vitest.config.js b/playground/pinia-vitest/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/pinia-vitest/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/pinia-with-tests/.gitignore b/playground/pinia-with-tests/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/pinia-with-tests/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/pinia-with-tests/README.md b/playground/pinia-with-tests/README.md new file mode 100644 index 000000000..f327a165f --- /dev/null +++ b/playground/pinia-with-tests/README.md @@ -0,0 +1,51 @@ +# pinia-with-tests + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/pinia-with-tests/cypress.config.js b/playground/pinia-with-tests/cypress.config.js new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/pinia-with-tests/cypress.config.js @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/pinia-with-tests/cypress/e2e/example.cy.js b/playground/pinia-with-tests/cypress/e2e/example.cy.js new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/pinia-with-tests/cypress/e2e/example.cy.js @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/pinia-with-tests/cypress/e2e/jsconfig.json b/playground/pinia-with-tests/cypress/e2e/jsconfig.json new file mode 100644 index 000000000..c790a70d6 --- /dev/null +++ b/playground/pinia-with-tests/cypress/e2e/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + }, + "include": ["./**/*", "../support/**/*"] +} diff --git a/playground/pinia-with-tests/cypress/fixtures/example.json b/playground/pinia-with-tests/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/pinia-with-tests/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/pinia-with-tests/cypress/support/commands.js b/playground/pinia-with-tests/cypress/support/commands.js new file mode 100644 index 000000000..119ab03f7 --- /dev/null +++ b/playground/pinia-with-tests/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) diff --git a/playground/pinia-with-tests/cypress/support/e2e.js b/playground/pinia-with-tests/cypress/support/e2e.js new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/pinia-with-tests/cypress/support/e2e.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/pinia-with-tests/index.html b/playground/pinia-with-tests/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/pinia-with-tests/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/pinia-with-tests/jsconfig.json b/playground/pinia-with-tests/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/pinia-with-tests/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/pinia-with-tests/package.json b/playground/pinia-with-tests/package.json new file mode 100644 index 000000000..6d97df386 --- /dev/null +++ b/playground/pinia-with-tests/package.json @@ -0,0 +1,27 @@ +{ + "name": "pinia-with-tests", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "start-server-and-test": "^2.0.3", + "vite": "^5.0.11", + "vitest": "^1.2.2" + } +} diff --git a/playground/pinia-with-tests/public/favicon.ico b/playground/pinia-with-tests/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/pinia-with-tests/src/App.vue b/playground/pinia-with-tests/src/App.vue new file mode 100644 index 000000000..b6f965e35 --- /dev/null +++ b/playground/pinia-with-tests/src/App.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/playground/pinia-with-tests/src/assets/logo.svg b/playground/pinia-with-tests/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/pinia-with-tests/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/pinia-with-tests/src/assets/main.css b/playground/pinia-with-tests/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/pinia-with-tests/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/pinia-with-tests/src/components/__tests__/HelloWorld.spec.js b/playground/pinia-with-tests/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/pinia-with-tests/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/pinia-with-tests/src/main.js b/playground/pinia-with-tests/src/main.js new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/pinia-with-tests/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/pinia-with-tests/src/stores/counter.js b/playground/pinia-with-tests/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/pinia-with-tests/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/pinia-with-tests/vite.config.js b/playground/pinia-with-tests/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/pinia-with-tests/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/pinia-with-tests/vitest.config.js b/playground/pinia-with-tests/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/pinia-with-tests/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/pinia/.gitignore b/playground/pinia/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/pinia/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/pinia/README.md b/playground/pinia/README.md new file mode 100644 index 000000000..f9e2c8efd --- /dev/null +++ b/playground/pinia/README.md @@ -0,0 +1,29 @@ +# pinia + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` diff --git a/playground/pinia/index.html b/playground/pinia/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/pinia/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/pinia/jsconfig.json b/playground/pinia/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/pinia/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/pinia/package.json b/playground/pinia/package.json new file mode 100644 index 000000000..9b6ab20cd --- /dev/null +++ b/playground/pinia/package.json @@ -0,0 +1,19 @@ +{ + "name": "pinia", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "vite": "^5.0.11" + } +} diff --git a/playground/pinia/public/favicon.ico b/playground/pinia/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/pinia/src/App.vue b/playground/pinia/src/App.vue new file mode 100644 index 000000000..b6f965e35 --- /dev/null +++ b/playground/pinia/src/App.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/playground/pinia/src/assets/logo.svg b/playground/pinia/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/pinia/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/pinia/src/assets/main.css b/playground/pinia/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/pinia/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/pinia/src/main.js b/playground/pinia/src/main.js new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/pinia/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/pinia/src/stores/counter.js b/playground/pinia/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/pinia/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/pinia/vite.config.js b/playground/pinia/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/pinia/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/playwright/.gitignore b/playground/playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/playwright/.vscode/extensions.json b/playground/playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/playwright/README.md b/playground/playwright/README.md new file mode 100644 index 000000000..0b67eaf34 --- /dev/null +++ b/playground/playwright/README.md @@ -0,0 +1,48 @@ +# playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/playwright/e2e/vue.spec.js b/playground/playwright/e2e/vue.spec.js new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/playwright/e2e/vue.spec.js @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/playwright/index.html b/playground/playwright/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/playwright/jsconfig.json b/playground/playwright/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/playwright/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/playwright/package.json b/playground/playwright/package.json new file mode 100644 index 000000000..9c63714fd --- /dev/null +++ b/playground/playwright/package.json @@ -0,0 +1,20 @@ +{ + "name": "playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:e2e": "playwright test" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@vitejs/plugin-vue": "^5.0.3", + "vite": "^5.0.11" + } +} diff --git a/playground/playwright/playwright.config.js b/playground/playwright/playwright.config.js new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/playwright/playwright.config.js @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/playwright/public/favicon.ico b/playground/playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/playwright/src/App.vue b/playground/playwright/src/App.vue new file mode 100644 index 000000000..b6f965e35 --- /dev/null +++ b/playground/playwright/src/App.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/playground/playwright/src/assets/logo.svg b/playground/playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/playwright/src/assets/main.css b/playground/playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/playwright/src/main.js b/playground/playwright/src/main.js new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/playwright/src/main.js @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/playwright/vite.config.js b/playground/playwright/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/playwright/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-cypress/.gitignore b/playground/router-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/router-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/router-cypress/README.md b/playground/router-cypress/README.md new file mode 100644 index 000000000..f9051d9b3 --- /dev/null +++ b/playground/router-cypress/README.md @@ -0,0 +1,51 @@ +# router-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Headed Component Tests with [Cypress Component Testing](https://on.cypress.io/component) + +```sh +pnpm test:unit:dev # or `pnpm test:unit` for headless testing +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/router-cypress/cypress.config.js b/playground/router-cypress/cypress.config.js new file mode 100644 index 000000000..c8fac1298 --- /dev/null +++ b/playground/router-cypress/cypress.config.js @@ -0,0 +1,15 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + }, + component: { + specPattern: 'src/**/__tests__/*.{cy,spec}.{js,ts,jsx,tsx}', + devServer: { + framework: 'vue', + bundler: 'vite' + } + } +}) diff --git a/playground/router-cypress/cypress/e2e/example.cy.js b/playground/router-cypress/cypress/e2e/example.cy.js new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/router-cypress/cypress/e2e/example.cy.js @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/router-cypress/cypress/e2e/jsconfig.json b/playground/router-cypress/cypress/e2e/jsconfig.json new file mode 100644 index 000000000..c790a70d6 --- /dev/null +++ b/playground/router-cypress/cypress/e2e/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + }, + "include": ["./**/*", "../support/**/*"] +} diff --git a/playground/router-cypress/cypress/fixtures/example.json b/playground/router-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/router-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/router-cypress/cypress/support/commands.js b/playground/router-cypress/cypress/support/commands.js new file mode 100644 index 000000000..119ab03f7 --- /dev/null +++ b/playground/router-cypress/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) diff --git a/playground/router-cypress/cypress/support/component-index.html b/playground/router-cypress/cypress/support/component-index.html new file mode 100644 index 000000000..5f9622ae2 --- /dev/null +++ b/playground/router-cypress/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + Components App + + +
+ + diff --git a/playground/router-cypress/cypress/support/component.js b/playground/router-cypress/cypress/support/component.js new file mode 100644 index 000000000..7283cad6d --- /dev/null +++ b/playground/router-cypress/cypress/support/component.js @@ -0,0 +1,30 @@ +// *********************************************************** +// This example support/component.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') + +// Import global styles +import '@/assets/main.css' + +import { mount } from 'cypress/vue' + +Cypress.Commands.add('mount', mount) + +// Example use: +// cy.mount(MyComponent) diff --git a/playground/router-cypress/cypress/support/e2e.js b/playground/router-cypress/cypress/support/e2e.js new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/router-cypress/cypress/support/e2e.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/router-cypress/index.html b/playground/router-cypress/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router-cypress/jsconfig.json b/playground/router-cypress/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router-cypress/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router-cypress/package.json b/playground/router-cypress/package.json new file mode 100644 index 000000000..7468b5dd9 --- /dev/null +++ b/playground/router-cypress/package.json @@ -0,0 +1,25 @@ +{ + "name": "router-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "test:unit": "cypress run --component", + "test:unit:dev": "cypress open --component" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "cypress": "^13.6.4", + "start-server-and-test": "^2.0.3", + "vite": "^5.0.11" + } +} diff --git a/playground/router-cypress/public/favicon.ico b/playground/router-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router-cypress/src/App.vue b/playground/router-cypress/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router-cypress/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router-cypress/src/assets/logo.svg b/playground/router-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router-cypress/src/assets/main.css b/playground/router-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router-cypress/src/components/__tests__/HelloWorld.cy.js b/playground/router-cypress/src/components/__tests__/HelloWorld.cy.js new file mode 100644 index 000000000..535a0e51c --- /dev/null +++ b/playground/router-cypress/src/components/__tests__/HelloWorld.cy.js @@ -0,0 +1,12 @@ +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('playground', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + }) + + it('renders properly', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + cy.get('h1').should('contain', 'Hello Cypress') + }) +}) diff --git a/playground/router-cypress/src/main.js b/playground/router-cypress/src/main.js new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/router-cypress/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/router-cypress/src/router/index.js b/playground/router-cypress/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router-cypress/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router-cypress/src/views/Home.vue b/playground/router-cypress/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router-cypress/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router-cypress/vite.config.js b/playground/router-cypress/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/router-cypress/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-nightwatch/.gitignore b/playground/router-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/router-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/router-nightwatch/.vscode/extensions.json b/playground/router-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/router-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/router-nightwatch/README.md b/playground/router-nightwatch/README.md new file mode 100644 index 000000000..922502c9d --- /dev/null +++ b/playground/router-nightwatch/README.md @@ -0,0 +1,52 @@ +# router-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.js +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/router-nightwatch/index.html b/playground/router-nightwatch/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router-nightwatch/jsconfig.json b/playground/router-nightwatch/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router-nightwatch/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router-nightwatch/nightwatch.conf.cjs b/playground/router-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/router-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/router-nightwatch/nightwatch/index.html b/playground/router-nightwatch/nightwatch/index.html new file mode 100644 index 000000000..b7e1ec765 --- /dev/null +++ b/playground/router-nightwatch/nightwatch/index.html @@ -0,0 +1,16 @@ + + + + + + + + + Vue Renderer + + + +
+ + + diff --git a/playground/router-nightwatch/package.json b/playground/router-nightwatch/package.json new file mode 100644 index 000000000..6db784511 --- /dev/null +++ b/playground/router-nightwatch/package.json @@ -0,0 +1,28 @@ +{ + "name": "router-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:e2e": "nightwatch tests/e2e/*", + "test:unit": "nightwatch src/**/__tests__/*" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "nightwatch": "^3.4.0", + "ts-node": "^10.9.2", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6" + } +} diff --git a/playground/router-nightwatch/public/favicon.ico b/playground/router-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router-nightwatch/src/App.vue b/playground/router-nightwatch/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router-nightwatch/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router-nightwatch/src/assets/logo.svg b/playground/router-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router-nightwatch/src/assets/main.css b/playground/router-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router-nightwatch/src/components/__tests__/HelloWorld.spec.js b/playground/router-nightwatch/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..810641e6e --- /dev/null +++ b/playground/router-nightwatch/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,14 @@ +describe('Hello World', function () { + before((browser) => { + browser.init() + }) + + it('renders properly', async function () { + const welcomeComponent = await browser.mountComponent('/src/components/HelloWorld.vue', {props: {msg: 'Hello Nightwatch'}}); + + browser.expect.element(welcomeComponent).to.be.present; + browser.expect.element('h1').text.to.contain('Hello Nightwatch'); + }) + + after((browser) => browser.end()) +}) diff --git a/playground/router-nightwatch/src/main.js b/playground/router-nightwatch/src/main.js new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/router-nightwatch/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/router-nightwatch/src/router/index.js b/playground/router-nightwatch/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router-nightwatch/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router-nightwatch/src/views/Home.vue b/playground/router-nightwatch/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router-nightwatch/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router-nightwatch/tests/e2e/example.js b/playground/router-nightwatch/tests/e2e/example.js new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/router-nightwatch/tests/e2e/example.js @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/router-nightwatch/vite.config.js b/playground/router-nightwatch/vite.config.js new file mode 100644 index 000000000..fd83c5b21 --- /dev/null +++ b/playground/router-nightwatch/vite.config.js @@ -0,0 +1,20 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + nightwatchPlugin({ + renderPage: './nightwatch/index.html' + }), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-pinia-cypress/.gitignore b/playground/router-pinia-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/router-pinia-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/router-pinia-cypress/README.md b/playground/router-pinia-cypress/README.md new file mode 100644 index 000000000..4fb2ddeca --- /dev/null +++ b/playground/router-pinia-cypress/README.md @@ -0,0 +1,51 @@ +# router-pinia-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Headed Component Tests with [Cypress Component Testing](https://on.cypress.io/component) + +```sh +pnpm test:unit:dev # or `pnpm test:unit` for headless testing +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/router-pinia-cypress/cypress.config.js b/playground/router-pinia-cypress/cypress.config.js new file mode 100644 index 000000000..c8fac1298 --- /dev/null +++ b/playground/router-pinia-cypress/cypress.config.js @@ -0,0 +1,15 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + }, + component: { + specPattern: 'src/**/__tests__/*.{cy,spec}.{js,ts,jsx,tsx}', + devServer: { + framework: 'vue', + bundler: 'vite' + } + } +}) diff --git a/playground/router-pinia-cypress/cypress/e2e/example.cy.js b/playground/router-pinia-cypress/cypress/e2e/example.cy.js new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/router-pinia-cypress/cypress/e2e/example.cy.js @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/router-pinia-cypress/cypress/e2e/jsconfig.json b/playground/router-pinia-cypress/cypress/e2e/jsconfig.json new file mode 100644 index 000000000..c790a70d6 --- /dev/null +++ b/playground/router-pinia-cypress/cypress/e2e/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + }, + "include": ["./**/*", "../support/**/*"] +} diff --git a/playground/router-pinia-cypress/cypress/fixtures/example.json b/playground/router-pinia-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/router-pinia-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/router-pinia-cypress/cypress/support/commands.js b/playground/router-pinia-cypress/cypress/support/commands.js new file mode 100644 index 000000000..119ab03f7 --- /dev/null +++ b/playground/router-pinia-cypress/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) diff --git a/playground/router-pinia-cypress/cypress/support/component-index.html b/playground/router-pinia-cypress/cypress/support/component-index.html new file mode 100644 index 000000000..5f9622ae2 --- /dev/null +++ b/playground/router-pinia-cypress/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + Components App + + +
+ + diff --git a/playground/router-pinia-cypress/cypress/support/component.js b/playground/router-pinia-cypress/cypress/support/component.js new file mode 100644 index 000000000..7283cad6d --- /dev/null +++ b/playground/router-pinia-cypress/cypress/support/component.js @@ -0,0 +1,30 @@ +// *********************************************************** +// This example support/component.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') + +// Import global styles +import '@/assets/main.css' + +import { mount } from 'cypress/vue' + +Cypress.Commands.add('mount', mount) + +// Example use: +// cy.mount(MyComponent) diff --git a/playground/router-pinia-cypress/cypress/support/e2e.js b/playground/router-pinia-cypress/cypress/support/e2e.js new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/router-pinia-cypress/cypress/support/e2e.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/router-pinia-cypress/index.html b/playground/router-pinia-cypress/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router-pinia-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router-pinia-cypress/jsconfig.json b/playground/router-pinia-cypress/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router-pinia-cypress/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router-pinia-cypress/package.json b/playground/router-pinia-cypress/package.json new file mode 100644 index 000000000..ad0dcfba6 --- /dev/null +++ b/playground/router-pinia-cypress/package.json @@ -0,0 +1,26 @@ +{ + "name": "router-pinia-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "test:unit": "cypress run --component", + "test:unit:dev": "cypress open --component" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "cypress": "^13.6.4", + "start-server-and-test": "^2.0.3", + "vite": "^5.0.11" + } +} diff --git a/playground/router-pinia-cypress/public/favicon.ico b/playground/router-pinia-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router-pinia-cypress/src/App.vue b/playground/router-pinia-cypress/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router-pinia-cypress/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router-pinia-cypress/src/assets/logo.svg b/playground/router-pinia-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router-pinia-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router-pinia-cypress/src/assets/main.css b/playground/router-pinia-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router-pinia-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router-pinia-cypress/src/components/__tests__/HelloWorld.cy.js b/playground/router-pinia-cypress/src/components/__tests__/HelloWorld.cy.js new file mode 100644 index 000000000..535a0e51c --- /dev/null +++ b/playground/router-pinia-cypress/src/components/__tests__/HelloWorld.cy.js @@ -0,0 +1,12 @@ +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('playground', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + }) + + it('renders properly', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + cy.get('h1').should('contain', 'Hello Cypress') + }) +}) diff --git a/playground/router-pinia-cypress/src/main.js b/playground/router-pinia-cypress/src/main.js new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/router-pinia-cypress/src/main.js @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/router-pinia-cypress/src/router/index.js b/playground/router-pinia-cypress/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router-pinia-cypress/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router-pinia-cypress/src/stores/counter.js b/playground/router-pinia-cypress/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/router-pinia-cypress/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/router-pinia-cypress/src/views/Home.vue b/playground/router-pinia-cypress/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router-pinia-cypress/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router-pinia-cypress/vite.config.js b/playground/router-pinia-cypress/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/router-pinia-cypress/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-pinia-nightwatch/.gitignore b/playground/router-pinia-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/router-pinia-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/router-pinia-nightwatch/.vscode/extensions.json b/playground/router-pinia-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/router-pinia-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/router-pinia-nightwatch/README.md b/playground/router-pinia-nightwatch/README.md new file mode 100644 index 000000000..36bb4c895 --- /dev/null +++ b/playground/router-pinia-nightwatch/README.md @@ -0,0 +1,52 @@ +# router-pinia-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.js +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/router-pinia-nightwatch/index.html b/playground/router-pinia-nightwatch/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router-pinia-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router-pinia-nightwatch/jsconfig.json b/playground/router-pinia-nightwatch/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router-pinia-nightwatch/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router-pinia-nightwatch/nightwatch.conf.cjs b/playground/router-pinia-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/router-pinia-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/router-pinia-nightwatch/nightwatch/index.html b/playground/router-pinia-nightwatch/nightwatch/index.html new file mode 100644 index 000000000..b7e1ec765 --- /dev/null +++ b/playground/router-pinia-nightwatch/nightwatch/index.html @@ -0,0 +1,16 @@ + + + + + + + + + Vue Renderer + + + +
+ + + diff --git a/playground/router-pinia-nightwatch/package.json b/playground/router-pinia-nightwatch/package.json new file mode 100644 index 000000000..12595fd51 --- /dev/null +++ b/playground/router-pinia-nightwatch/package.json @@ -0,0 +1,29 @@ +{ + "name": "router-pinia-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:e2e": "nightwatch tests/e2e/*", + "test:unit": "nightwatch src/**/__tests__/*" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "nightwatch": "^3.4.0", + "ts-node": "^10.9.2", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6" + } +} diff --git a/playground/router-pinia-nightwatch/public/favicon.ico b/playground/router-pinia-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router-pinia-nightwatch/src/App.vue b/playground/router-pinia-nightwatch/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router-pinia-nightwatch/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router-pinia-nightwatch/src/assets/logo.svg b/playground/router-pinia-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router-pinia-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router-pinia-nightwatch/src/assets/main.css b/playground/router-pinia-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router-pinia-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.js b/playground/router-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..810641e6e --- /dev/null +++ b/playground/router-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,14 @@ +describe('Hello World', function () { + before((browser) => { + browser.init() + }) + + it('renders properly', async function () { + const welcomeComponent = await browser.mountComponent('/src/components/HelloWorld.vue', {props: {msg: 'Hello Nightwatch'}}); + + browser.expect.element(welcomeComponent).to.be.present; + browser.expect.element('h1').text.to.contain('Hello Nightwatch'); + }) + + after((browser) => browser.end()) +}) diff --git a/playground/router-pinia-nightwatch/src/main.js b/playground/router-pinia-nightwatch/src/main.js new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/router-pinia-nightwatch/src/main.js @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/router-pinia-nightwatch/src/router/index.js b/playground/router-pinia-nightwatch/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router-pinia-nightwatch/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router-pinia-nightwatch/src/stores/counter.js b/playground/router-pinia-nightwatch/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/router-pinia-nightwatch/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/router-pinia-nightwatch/src/views/Home.vue b/playground/router-pinia-nightwatch/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router-pinia-nightwatch/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router-pinia-nightwatch/tests/e2e/example.js b/playground/router-pinia-nightwatch/tests/e2e/example.js new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/router-pinia-nightwatch/tests/e2e/example.js @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/router-pinia-nightwatch/vite.config.js b/playground/router-pinia-nightwatch/vite.config.js new file mode 100644 index 000000000..fd83c5b21 --- /dev/null +++ b/playground/router-pinia-nightwatch/vite.config.js @@ -0,0 +1,20 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + nightwatchPlugin({ + renderPage: './nightwatch/index.html' + }), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-pinia-playwright/.gitignore b/playground/router-pinia-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/router-pinia-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/router-pinia-playwright/.vscode/extensions.json b/playground/router-pinia-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/router-pinia-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/router-pinia-playwright/README.md b/playground/router-pinia-playwright/README.md new file mode 100644 index 000000000..75001ce01 --- /dev/null +++ b/playground/router-pinia-playwright/README.md @@ -0,0 +1,48 @@ +# router-pinia-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/router-pinia-playwright/e2e/vue.spec.js b/playground/router-pinia-playwright/e2e/vue.spec.js new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/router-pinia-playwright/e2e/vue.spec.js @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/router-pinia-playwright/index.html b/playground/router-pinia-playwright/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router-pinia-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router-pinia-playwright/jsconfig.json b/playground/router-pinia-playwright/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router-pinia-playwright/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router-pinia-playwright/package.json b/playground/router-pinia-playwright/package.json new file mode 100644 index 000000000..e9dc2a329 --- /dev/null +++ b/playground/router-pinia-playwright/package.json @@ -0,0 +1,22 @@ +{ + "name": "router-pinia-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:e2e": "playwright test" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@vitejs/plugin-vue": "^5.0.3", + "vite": "^5.0.11" + } +} diff --git a/playground/router-pinia-playwright/playwright.config.js b/playground/router-pinia-playwright/playwright.config.js new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/router-pinia-playwright/playwright.config.js @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/router-pinia-playwright/public/favicon.ico b/playground/router-pinia-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router-pinia-playwright/src/App.vue b/playground/router-pinia-playwright/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router-pinia-playwright/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router-pinia-playwright/src/assets/logo.svg b/playground/router-pinia-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router-pinia-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router-pinia-playwright/src/assets/main.css b/playground/router-pinia-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router-pinia-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router-pinia-playwright/src/main.js b/playground/router-pinia-playwright/src/main.js new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/router-pinia-playwright/src/main.js @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/router-pinia-playwright/src/router/index.js b/playground/router-pinia-playwright/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router-pinia-playwright/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router-pinia-playwright/src/stores/counter.js b/playground/router-pinia-playwright/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/router-pinia-playwright/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/router-pinia-playwright/src/views/Home.vue b/playground/router-pinia-playwright/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router-pinia-playwright/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router-pinia-playwright/vite.config.js b/playground/router-pinia-playwright/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/router-pinia-playwright/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-pinia-vitest-cypress/.gitignore b/playground/router-pinia-vitest-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/router-pinia-vitest-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/router-pinia-vitest-cypress/README.md b/playground/router-pinia-vitest-cypress/README.md new file mode 100644 index 000000000..c7d98a844 --- /dev/null +++ b/playground/router-pinia-vitest-cypress/README.md @@ -0,0 +1,51 @@ +# router-pinia-vitest-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/router-pinia-vitest-cypress/cypress.config.js b/playground/router-pinia-vitest-cypress/cypress.config.js new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/router-pinia-vitest-cypress/cypress.config.js @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/router-pinia-vitest-cypress/cypress/e2e/example.cy.js b/playground/router-pinia-vitest-cypress/cypress/e2e/example.cy.js new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/router-pinia-vitest-cypress/cypress/e2e/example.cy.js @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/router-pinia-vitest-cypress/cypress/e2e/jsconfig.json b/playground/router-pinia-vitest-cypress/cypress/e2e/jsconfig.json new file mode 100644 index 000000000..c790a70d6 --- /dev/null +++ b/playground/router-pinia-vitest-cypress/cypress/e2e/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + }, + "include": ["./**/*", "../support/**/*"] +} diff --git a/playground/router-pinia-vitest-cypress/cypress/fixtures/example.json b/playground/router-pinia-vitest-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/router-pinia-vitest-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/router-pinia-vitest-cypress/cypress/support/commands.js b/playground/router-pinia-vitest-cypress/cypress/support/commands.js new file mode 100644 index 000000000..119ab03f7 --- /dev/null +++ b/playground/router-pinia-vitest-cypress/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) diff --git a/playground/router-pinia-vitest-cypress/cypress/support/e2e.js b/playground/router-pinia-vitest-cypress/cypress/support/e2e.js new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/router-pinia-vitest-cypress/cypress/support/e2e.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/router-pinia-vitest-cypress/index.html b/playground/router-pinia-vitest-cypress/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router-pinia-vitest-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router-pinia-vitest-cypress/jsconfig.json b/playground/router-pinia-vitest-cypress/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router-pinia-vitest-cypress/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router-pinia-vitest-cypress/package.json b/playground/router-pinia-vitest-cypress/package.json new file mode 100644 index 000000000..04c81c421 --- /dev/null +++ b/playground/router-pinia-vitest-cypress/package.json @@ -0,0 +1,28 @@ +{ + "name": "router-pinia-vitest-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "start-server-and-test": "^2.0.3", + "vite": "^5.0.11", + "vitest": "^1.2.2" + } +} diff --git a/playground/router-pinia-vitest-cypress/public/favicon.ico b/playground/router-pinia-vitest-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router-pinia-vitest-cypress/src/App.vue b/playground/router-pinia-vitest-cypress/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router-pinia-vitest-cypress/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router-pinia-vitest-cypress/src/assets/logo.svg b/playground/router-pinia-vitest-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router-pinia-vitest-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router-pinia-vitest-cypress/src/assets/main.css b/playground/router-pinia-vitest-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router-pinia-vitest-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.js b/playground/router-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/router-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/router-pinia-vitest-cypress/src/main.js b/playground/router-pinia-vitest-cypress/src/main.js new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/router-pinia-vitest-cypress/src/main.js @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/router-pinia-vitest-cypress/src/router/index.js b/playground/router-pinia-vitest-cypress/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router-pinia-vitest-cypress/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router-pinia-vitest-cypress/src/stores/counter.js b/playground/router-pinia-vitest-cypress/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/router-pinia-vitest-cypress/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/router-pinia-vitest-cypress/src/views/Home.vue b/playground/router-pinia-vitest-cypress/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router-pinia-vitest-cypress/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router-pinia-vitest-cypress/vite.config.js b/playground/router-pinia-vitest-cypress/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/router-pinia-vitest-cypress/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-pinia-vitest-cypress/vitest.config.js b/playground/router-pinia-vitest-cypress/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/router-pinia-vitest-cypress/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/router-pinia-vitest-nightwatch/.gitignore b/playground/router-pinia-vitest-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/router-pinia-vitest-nightwatch/.vscode/extensions.json b/playground/router-pinia-vitest-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/router-pinia-vitest-nightwatch/README.md b/playground/router-pinia-vitest-nightwatch/README.md new file mode 100644 index 000000000..dc5fd329e --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/README.md @@ -0,0 +1,58 @@ +# router-pinia-vitest-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.js +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/router-pinia-vitest-nightwatch/index.html b/playground/router-pinia-vitest-nightwatch/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router-pinia-vitest-nightwatch/jsconfig.json b/playground/router-pinia-vitest-nightwatch/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router-pinia-vitest-nightwatch/nightwatch.conf.cjs b/playground/router-pinia-vitest-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/router-pinia-vitest-nightwatch/package.json b/playground/router-pinia-vitest-nightwatch/package.json new file mode 100644 index 000000000..3b3535b01 --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/package.json @@ -0,0 +1,31 @@ +{ + "name": "router-pinia-vitest-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "nightwatch tests/e2e/*" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "jsdom": "^24.0.0", + "nightwatch": "^3.4.0", + "ts-node": "^10.9.2", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vitest": "^1.2.2" + } +} diff --git a/playground/router-pinia-vitest-nightwatch/public/favicon.ico b/playground/router-pinia-vitest-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router-pinia-vitest-nightwatch/src/App.vue b/playground/router-pinia-vitest-nightwatch/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router-pinia-vitest-nightwatch/src/assets/logo.svg b/playground/router-pinia-vitest-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router-pinia-vitest-nightwatch/src/assets/main.css b/playground/router-pinia-vitest-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.js b/playground/router-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/router-pinia-vitest-nightwatch/src/main.js b/playground/router-pinia-vitest-nightwatch/src/main.js new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/src/main.js @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/router-pinia-vitest-nightwatch/src/router/index.js b/playground/router-pinia-vitest-nightwatch/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router-pinia-vitest-nightwatch/src/stores/counter.js b/playground/router-pinia-vitest-nightwatch/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/router-pinia-vitest-nightwatch/src/views/Home.vue b/playground/router-pinia-vitest-nightwatch/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router-pinia-vitest-nightwatch/tests/e2e/example.js b/playground/router-pinia-vitest-nightwatch/tests/e2e/example.js new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/tests/e2e/example.js @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/router-pinia-vitest-nightwatch/vite.config.js b/playground/router-pinia-vitest-nightwatch/vite.config.js new file mode 100644 index 000000000..be3cb9c57 --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/vite.config.js @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + nightwatchPlugin(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-pinia-vitest-nightwatch/vitest.config.js b/playground/router-pinia-vitest-nightwatch/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/router-pinia-vitest-nightwatch/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/router-pinia-vitest-playwright/.gitignore b/playground/router-pinia-vitest-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/router-pinia-vitest-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/router-pinia-vitest-playwright/.vscode/extensions.json b/playground/router-pinia-vitest-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/router-pinia-vitest-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/router-pinia-vitest-playwright/README.md b/playground/router-pinia-vitest-playwright/README.md new file mode 100644 index 000000000..189517a50 --- /dev/null +++ b/playground/router-pinia-vitest-playwright/README.md @@ -0,0 +1,54 @@ +# router-pinia-vitest-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/router-pinia-vitest-playwright/e2e/vue.spec.js b/playground/router-pinia-vitest-playwright/e2e/vue.spec.js new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/router-pinia-vitest-playwright/e2e/vue.spec.js @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/router-pinia-vitest-playwright/index.html b/playground/router-pinia-vitest-playwright/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router-pinia-vitest-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router-pinia-vitest-playwright/jsconfig.json b/playground/router-pinia-vitest-playwright/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router-pinia-vitest-playwright/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router-pinia-vitest-playwright/package.json b/playground/router-pinia-vitest-playwright/package.json new file mode 100644 index 000000000..14c53581b --- /dev/null +++ b/playground/router-pinia-vitest-playwright/package.json @@ -0,0 +1,26 @@ +{ + "name": "router-pinia-vitest-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "playwright test" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "jsdom": "^24.0.0", + "vite": "^5.0.11", + "vitest": "^1.2.2" + } +} diff --git a/playground/router-pinia-vitest-playwright/playwright.config.js b/playground/router-pinia-vitest-playwright/playwright.config.js new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/router-pinia-vitest-playwright/playwright.config.js @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/router-pinia-vitest-playwright/public/favicon.ico b/playground/router-pinia-vitest-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router-pinia-vitest-playwright/src/App.vue b/playground/router-pinia-vitest-playwright/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router-pinia-vitest-playwright/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router-pinia-vitest-playwright/src/assets/logo.svg b/playground/router-pinia-vitest-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router-pinia-vitest-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router-pinia-vitest-playwright/src/assets/main.css b/playground/router-pinia-vitest-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router-pinia-vitest-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.js b/playground/router-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/router-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/router-pinia-vitest-playwright/src/main.js b/playground/router-pinia-vitest-playwright/src/main.js new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/router-pinia-vitest-playwright/src/main.js @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/router-pinia-vitest-playwright/src/router/index.js b/playground/router-pinia-vitest-playwright/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router-pinia-vitest-playwright/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router-pinia-vitest-playwright/src/stores/counter.js b/playground/router-pinia-vitest-playwright/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/router-pinia-vitest-playwright/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/router-pinia-vitest-playwright/src/views/Home.vue b/playground/router-pinia-vitest-playwright/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router-pinia-vitest-playwright/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router-pinia-vitest-playwright/vite.config.js b/playground/router-pinia-vitest-playwright/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/router-pinia-vitest-playwright/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-pinia-vitest-playwright/vitest.config.js b/playground/router-pinia-vitest-playwright/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/router-pinia-vitest-playwright/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/router-pinia-vitest/.gitignore b/playground/router-pinia-vitest/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/router-pinia-vitest/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/router-pinia-vitest/README.md b/playground/router-pinia-vitest/README.md new file mode 100644 index 000000000..471aea4b2 --- /dev/null +++ b/playground/router-pinia-vitest/README.md @@ -0,0 +1,35 @@ +# router-pinia-vitest + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` diff --git a/playground/router-pinia-vitest/index.html b/playground/router-pinia-vitest/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router-pinia-vitest/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router-pinia-vitest/jsconfig.json b/playground/router-pinia-vitest/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router-pinia-vitest/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router-pinia-vitest/package.json b/playground/router-pinia-vitest/package.json new file mode 100644 index 000000000..33a4f0521 --- /dev/null +++ b/playground/router-pinia-vitest/package.json @@ -0,0 +1,24 @@ +{ + "name": "router-pinia-vitest", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "jsdom": "^24.0.0", + "vite": "^5.0.11", + "vitest": "^1.2.2" + } +} diff --git a/playground/router-pinia-vitest/public/favicon.ico b/playground/router-pinia-vitest/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router-pinia-vitest/src/App.vue b/playground/router-pinia-vitest/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router-pinia-vitest/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router-pinia-vitest/src/assets/logo.svg b/playground/router-pinia-vitest/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router-pinia-vitest/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router-pinia-vitest/src/assets/main.css b/playground/router-pinia-vitest/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router-pinia-vitest/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router-pinia-vitest/src/components/__tests__/HelloWorld.spec.js b/playground/router-pinia-vitest/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/router-pinia-vitest/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/router-pinia-vitest/src/main.js b/playground/router-pinia-vitest/src/main.js new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/router-pinia-vitest/src/main.js @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/router-pinia-vitest/src/router/index.js b/playground/router-pinia-vitest/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router-pinia-vitest/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router-pinia-vitest/src/stores/counter.js b/playground/router-pinia-vitest/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/router-pinia-vitest/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/router-pinia-vitest/src/views/Home.vue b/playground/router-pinia-vitest/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router-pinia-vitest/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router-pinia-vitest/vite.config.js b/playground/router-pinia-vitest/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/router-pinia-vitest/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-pinia-vitest/vitest.config.js b/playground/router-pinia-vitest/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/router-pinia-vitest/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/router-pinia-with-tests/.gitignore b/playground/router-pinia-with-tests/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/router-pinia-with-tests/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/router-pinia-with-tests/README.md b/playground/router-pinia-with-tests/README.md new file mode 100644 index 000000000..57e507fef --- /dev/null +++ b/playground/router-pinia-with-tests/README.md @@ -0,0 +1,51 @@ +# router-pinia-with-tests + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/router-pinia-with-tests/cypress.config.js b/playground/router-pinia-with-tests/cypress.config.js new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/router-pinia-with-tests/cypress.config.js @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/router-pinia-with-tests/cypress/e2e/example.cy.js b/playground/router-pinia-with-tests/cypress/e2e/example.cy.js new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/router-pinia-with-tests/cypress/e2e/example.cy.js @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/router-pinia-with-tests/cypress/e2e/jsconfig.json b/playground/router-pinia-with-tests/cypress/e2e/jsconfig.json new file mode 100644 index 000000000..c790a70d6 --- /dev/null +++ b/playground/router-pinia-with-tests/cypress/e2e/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + }, + "include": ["./**/*", "../support/**/*"] +} diff --git a/playground/router-pinia-with-tests/cypress/fixtures/example.json b/playground/router-pinia-with-tests/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/router-pinia-with-tests/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/router-pinia-with-tests/cypress/support/commands.js b/playground/router-pinia-with-tests/cypress/support/commands.js new file mode 100644 index 000000000..119ab03f7 --- /dev/null +++ b/playground/router-pinia-with-tests/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) diff --git a/playground/router-pinia-with-tests/cypress/support/e2e.js b/playground/router-pinia-with-tests/cypress/support/e2e.js new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/router-pinia-with-tests/cypress/support/e2e.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/router-pinia-with-tests/index.html b/playground/router-pinia-with-tests/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router-pinia-with-tests/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router-pinia-with-tests/jsconfig.json b/playground/router-pinia-with-tests/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router-pinia-with-tests/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router-pinia-with-tests/package.json b/playground/router-pinia-with-tests/package.json new file mode 100644 index 000000000..023e61c8d --- /dev/null +++ b/playground/router-pinia-with-tests/package.json @@ -0,0 +1,28 @@ +{ + "name": "router-pinia-with-tests", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "start-server-and-test": "^2.0.3", + "vite": "^5.0.11", + "vitest": "^1.2.2" + } +} diff --git a/playground/router-pinia-with-tests/public/favicon.ico b/playground/router-pinia-with-tests/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router-pinia-with-tests/src/App.vue b/playground/router-pinia-with-tests/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router-pinia-with-tests/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router-pinia-with-tests/src/assets/logo.svg b/playground/router-pinia-with-tests/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router-pinia-with-tests/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router-pinia-with-tests/src/assets/main.css b/playground/router-pinia-with-tests/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router-pinia-with-tests/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router-pinia-with-tests/src/components/__tests__/HelloWorld.spec.js b/playground/router-pinia-with-tests/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/router-pinia-with-tests/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/router-pinia-with-tests/src/main.js b/playground/router-pinia-with-tests/src/main.js new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/router-pinia-with-tests/src/main.js @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/router-pinia-with-tests/src/router/index.js b/playground/router-pinia-with-tests/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router-pinia-with-tests/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router-pinia-with-tests/src/stores/counter.js b/playground/router-pinia-with-tests/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/router-pinia-with-tests/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/router-pinia-with-tests/src/views/Home.vue b/playground/router-pinia-with-tests/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router-pinia-with-tests/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router-pinia-with-tests/vite.config.js b/playground/router-pinia-with-tests/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/router-pinia-with-tests/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-pinia-with-tests/vitest.config.js b/playground/router-pinia-with-tests/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/router-pinia-with-tests/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/router-pinia/.gitignore b/playground/router-pinia/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/router-pinia/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/router-pinia/README.md b/playground/router-pinia/README.md new file mode 100644 index 000000000..514afe14d --- /dev/null +++ b/playground/router-pinia/README.md @@ -0,0 +1,29 @@ +# router-pinia + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` diff --git a/playground/router-pinia/index.html b/playground/router-pinia/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router-pinia/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router-pinia/jsconfig.json b/playground/router-pinia/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router-pinia/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router-pinia/package.json b/playground/router-pinia/package.json new file mode 100644 index 000000000..058b87980 --- /dev/null +++ b/playground/router-pinia/package.json @@ -0,0 +1,20 @@ +{ + "name": "router-pinia", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "vite": "^5.0.11" + } +} diff --git a/playground/router-pinia/public/favicon.ico b/playground/router-pinia/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router-pinia/src/App.vue b/playground/router-pinia/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router-pinia/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router-pinia/src/assets/logo.svg b/playground/router-pinia/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router-pinia/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router-pinia/src/assets/main.css b/playground/router-pinia/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router-pinia/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router-pinia/src/main.js b/playground/router-pinia/src/main.js new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/router-pinia/src/main.js @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/router-pinia/src/router/index.js b/playground/router-pinia/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router-pinia/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router-pinia/src/stores/counter.js b/playground/router-pinia/src/stores/counter.js new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/router-pinia/src/stores/counter.js @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/router-pinia/src/views/Home.vue b/playground/router-pinia/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router-pinia/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router-pinia/vite.config.js b/playground/router-pinia/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/router-pinia/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-playwright/.gitignore b/playground/router-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/router-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/router-playwright/.vscode/extensions.json b/playground/router-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/router-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/router-playwright/README.md b/playground/router-playwright/README.md new file mode 100644 index 000000000..132a6acf6 --- /dev/null +++ b/playground/router-playwright/README.md @@ -0,0 +1,48 @@ +# router-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/router-playwright/e2e/vue.spec.js b/playground/router-playwright/e2e/vue.spec.js new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/router-playwright/e2e/vue.spec.js @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/router-playwright/index.html b/playground/router-playwright/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router-playwright/jsconfig.json b/playground/router-playwright/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router-playwright/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router-playwright/package.json b/playground/router-playwright/package.json new file mode 100644 index 000000000..aa5c75fd3 --- /dev/null +++ b/playground/router-playwright/package.json @@ -0,0 +1,21 @@ +{ + "name": "router-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:e2e": "playwright test" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@vitejs/plugin-vue": "^5.0.3", + "vite": "^5.0.11" + } +} diff --git a/playground/router-playwright/playwright.config.js b/playground/router-playwright/playwright.config.js new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/router-playwright/playwright.config.js @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/router-playwright/public/favicon.ico b/playground/router-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router-playwright/src/App.vue b/playground/router-playwright/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router-playwright/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router-playwright/src/assets/logo.svg b/playground/router-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router-playwright/src/assets/main.css b/playground/router-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router-playwright/src/main.js b/playground/router-playwright/src/main.js new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/router-playwright/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/router-playwright/src/router/index.js b/playground/router-playwright/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router-playwright/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router-playwright/src/views/Home.vue b/playground/router-playwright/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router-playwright/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router-playwright/vite.config.js b/playground/router-playwright/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/router-playwright/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-vitest-cypress/.gitignore b/playground/router-vitest-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/router-vitest-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/router-vitest-cypress/README.md b/playground/router-vitest-cypress/README.md new file mode 100644 index 000000000..798e3f4e9 --- /dev/null +++ b/playground/router-vitest-cypress/README.md @@ -0,0 +1,51 @@ +# router-vitest-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/router-vitest-cypress/cypress.config.js b/playground/router-vitest-cypress/cypress.config.js new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/router-vitest-cypress/cypress.config.js @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/router-vitest-cypress/cypress/e2e/example.cy.js b/playground/router-vitest-cypress/cypress/e2e/example.cy.js new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/router-vitest-cypress/cypress/e2e/example.cy.js @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/router-vitest-cypress/cypress/e2e/jsconfig.json b/playground/router-vitest-cypress/cypress/e2e/jsconfig.json new file mode 100644 index 000000000..c790a70d6 --- /dev/null +++ b/playground/router-vitest-cypress/cypress/e2e/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + }, + "include": ["./**/*", "../support/**/*"] +} diff --git a/playground/router-vitest-cypress/cypress/fixtures/example.json b/playground/router-vitest-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/router-vitest-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/router-vitest-cypress/cypress/support/commands.js b/playground/router-vitest-cypress/cypress/support/commands.js new file mode 100644 index 000000000..119ab03f7 --- /dev/null +++ b/playground/router-vitest-cypress/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) diff --git a/playground/router-vitest-cypress/cypress/support/e2e.js b/playground/router-vitest-cypress/cypress/support/e2e.js new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/router-vitest-cypress/cypress/support/e2e.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/router-vitest-cypress/index.html b/playground/router-vitest-cypress/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router-vitest-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router-vitest-cypress/jsconfig.json b/playground/router-vitest-cypress/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router-vitest-cypress/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router-vitest-cypress/package.json b/playground/router-vitest-cypress/package.json new file mode 100644 index 000000000..7ab1cbc4b --- /dev/null +++ b/playground/router-vitest-cypress/package.json @@ -0,0 +1,27 @@ +{ + "name": "router-vitest-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "start-server-and-test": "^2.0.3", + "vite": "^5.0.11", + "vitest": "^1.2.2" + } +} diff --git a/playground/router-vitest-cypress/public/favicon.ico b/playground/router-vitest-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router-vitest-cypress/src/App.vue b/playground/router-vitest-cypress/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router-vitest-cypress/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router-vitest-cypress/src/assets/logo.svg b/playground/router-vitest-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router-vitest-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router-vitest-cypress/src/assets/main.css b/playground/router-vitest-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router-vitest-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router-vitest-cypress/src/components/__tests__/HelloWorld.spec.js b/playground/router-vitest-cypress/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/router-vitest-cypress/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/router-vitest-cypress/src/main.js b/playground/router-vitest-cypress/src/main.js new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/router-vitest-cypress/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/router-vitest-cypress/src/router/index.js b/playground/router-vitest-cypress/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router-vitest-cypress/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router-vitest-cypress/src/views/Home.vue b/playground/router-vitest-cypress/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router-vitest-cypress/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router-vitest-cypress/vite.config.js b/playground/router-vitest-cypress/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/router-vitest-cypress/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-vitest-cypress/vitest.config.js b/playground/router-vitest-cypress/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/router-vitest-cypress/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/router-vitest-nightwatch/.gitignore b/playground/router-vitest-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/router-vitest-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/router-vitest-nightwatch/.vscode/extensions.json b/playground/router-vitest-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/router-vitest-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/router-vitest-nightwatch/README.md b/playground/router-vitest-nightwatch/README.md new file mode 100644 index 000000000..4f57de031 --- /dev/null +++ b/playground/router-vitest-nightwatch/README.md @@ -0,0 +1,58 @@ +# router-vitest-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.js +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/router-vitest-nightwatch/index.html b/playground/router-vitest-nightwatch/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router-vitest-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router-vitest-nightwatch/jsconfig.json b/playground/router-vitest-nightwatch/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router-vitest-nightwatch/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router-vitest-nightwatch/nightwatch.conf.cjs b/playground/router-vitest-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/router-vitest-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/router-vitest-nightwatch/package.json b/playground/router-vitest-nightwatch/package.json new file mode 100644 index 000000000..ac9d59f80 --- /dev/null +++ b/playground/router-vitest-nightwatch/package.json @@ -0,0 +1,30 @@ +{ + "name": "router-vitest-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "nightwatch tests/e2e/*" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "jsdom": "^24.0.0", + "nightwatch": "^3.4.0", + "ts-node": "^10.9.2", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vitest": "^1.2.2" + } +} diff --git a/playground/router-vitest-nightwatch/public/favicon.ico b/playground/router-vitest-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router-vitest-nightwatch/src/App.vue b/playground/router-vitest-nightwatch/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router-vitest-nightwatch/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router-vitest-nightwatch/src/assets/logo.svg b/playground/router-vitest-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router-vitest-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router-vitest-nightwatch/src/assets/main.css b/playground/router-vitest-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router-vitest-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.js b/playground/router-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/router-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/router-vitest-nightwatch/src/main.js b/playground/router-vitest-nightwatch/src/main.js new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/router-vitest-nightwatch/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/router-vitest-nightwatch/src/router/index.js b/playground/router-vitest-nightwatch/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router-vitest-nightwatch/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router-vitest-nightwatch/src/views/Home.vue b/playground/router-vitest-nightwatch/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router-vitest-nightwatch/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router-vitest-nightwatch/tests/e2e/example.js b/playground/router-vitest-nightwatch/tests/e2e/example.js new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/router-vitest-nightwatch/tests/e2e/example.js @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/router-vitest-nightwatch/vite.config.js b/playground/router-vitest-nightwatch/vite.config.js new file mode 100644 index 000000000..be3cb9c57 --- /dev/null +++ b/playground/router-vitest-nightwatch/vite.config.js @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + nightwatchPlugin(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-vitest-nightwatch/vitest.config.js b/playground/router-vitest-nightwatch/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/router-vitest-nightwatch/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/router-vitest-playwright/.gitignore b/playground/router-vitest-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/router-vitest-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/router-vitest-playwright/.vscode/extensions.json b/playground/router-vitest-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/router-vitest-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/router-vitest-playwright/README.md b/playground/router-vitest-playwright/README.md new file mode 100644 index 000000000..ad3a99524 --- /dev/null +++ b/playground/router-vitest-playwright/README.md @@ -0,0 +1,54 @@ +# router-vitest-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/router-vitest-playwright/e2e/vue.spec.js b/playground/router-vitest-playwright/e2e/vue.spec.js new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/router-vitest-playwright/e2e/vue.spec.js @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/router-vitest-playwright/index.html b/playground/router-vitest-playwright/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router-vitest-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router-vitest-playwright/jsconfig.json b/playground/router-vitest-playwright/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router-vitest-playwright/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router-vitest-playwright/package.json b/playground/router-vitest-playwright/package.json new file mode 100644 index 000000000..41b760bd5 --- /dev/null +++ b/playground/router-vitest-playwright/package.json @@ -0,0 +1,25 @@ +{ + "name": "router-vitest-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "playwright test" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "jsdom": "^24.0.0", + "vite": "^5.0.11", + "vitest": "^1.2.2" + } +} diff --git a/playground/router-vitest-playwright/playwright.config.js b/playground/router-vitest-playwright/playwright.config.js new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/router-vitest-playwright/playwright.config.js @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/router-vitest-playwright/public/favicon.ico b/playground/router-vitest-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router-vitest-playwright/src/App.vue b/playground/router-vitest-playwright/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router-vitest-playwright/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router-vitest-playwright/src/assets/logo.svg b/playground/router-vitest-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router-vitest-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router-vitest-playwright/src/assets/main.css b/playground/router-vitest-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router-vitest-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router-vitest-playwright/src/components/__tests__/HelloWorld.spec.js b/playground/router-vitest-playwright/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/router-vitest-playwright/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/router-vitest-playwright/src/main.js b/playground/router-vitest-playwright/src/main.js new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/router-vitest-playwright/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/router-vitest-playwright/src/router/index.js b/playground/router-vitest-playwright/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router-vitest-playwright/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router-vitest-playwright/src/views/Home.vue b/playground/router-vitest-playwright/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router-vitest-playwright/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router-vitest-playwright/vite.config.js b/playground/router-vitest-playwright/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/router-vitest-playwright/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-vitest-playwright/vitest.config.js b/playground/router-vitest-playwright/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/router-vitest-playwright/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/router-vitest/.gitignore b/playground/router-vitest/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/router-vitest/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/router-vitest/README.md b/playground/router-vitest/README.md new file mode 100644 index 000000000..25e8bcb78 --- /dev/null +++ b/playground/router-vitest/README.md @@ -0,0 +1,35 @@ +# router-vitest + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` diff --git a/playground/router-vitest/index.html b/playground/router-vitest/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router-vitest/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router-vitest/jsconfig.json b/playground/router-vitest/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router-vitest/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router-vitest/package.json b/playground/router-vitest/package.json new file mode 100644 index 000000000..92246b3ea --- /dev/null +++ b/playground/router-vitest/package.json @@ -0,0 +1,23 @@ +{ + "name": "router-vitest", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "jsdom": "^24.0.0", + "vite": "^5.0.11", + "vitest": "^1.2.2" + } +} diff --git a/playground/router-vitest/public/favicon.ico b/playground/router-vitest/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router-vitest/src/App.vue b/playground/router-vitest/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router-vitest/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router-vitest/src/assets/logo.svg b/playground/router-vitest/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router-vitest/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router-vitest/src/assets/main.css b/playground/router-vitest/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router-vitest/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router-vitest/src/components/__tests__/HelloWorld.spec.js b/playground/router-vitest/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/router-vitest/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/router-vitest/src/main.js b/playground/router-vitest/src/main.js new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/router-vitest/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/router-vitest/src/router/index.js b/playground/router-vitest/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router-vitest/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router-vitest/src/views/Home.vue b/playground/router-vitest/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router-vitest/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router-vitest/vite.config.js b/playground/router-vitest/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/router-vitest/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-vitest/vitest.config.js b/playground/router-vitest/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/router-vitest/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/router-with-tests/.gitignore b/playground/router-with-tests/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/router-with-tests/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/router-with-tests/README.md b/playground/router-with-tests/README.md new file mode 100644 index 000000000..67340fc9f --- /dev/null +++ b/playground/router-with-tests/README.md @@ -0,0 +1,51 @@ +# router-with-tests + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/router-with-tests/cypress.config.js b/playground/router-with-tests/cypress.config.js new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/router-with-tests/cypress.config.js @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/router-with-tests/cypress/e2e/example.cy.js b/playground/router-with-tests/cypress/e2e/example.cy.js new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/router-with-tests/cypress/e2e/example.cy.js @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/router-with-tests/cypress/e2e/jsconfig.json b/playground/router-with-tests/cypress/e2e/jsconfig.json new file mode 100644 index 000000000..c790a70d6 --- /dev/null +++ b/playground/router-with-tests/cypress/e2e/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + }, + "include": ["./**/*", "../support/**/*"] +} diff --git a/playground/router-with-tests/cypress/fixtures/example.json b/playground/router-with-tests/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/router-with-tests/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/router-with-tests/cypress/support/commands.js b/playground/router-with-tests/cypress/support/commands.js new file mode 100644 index 000000000..119ab03f7 --- /dev/null +++ b/playground/router-with-tests/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) diff --git a/playground/router-with-tests/cypress/support/e2e.js b/playground/router-with-tests/cypress/support/e2e.js new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/router-with-tests/cypress/support/e2e.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/router-with-tests/index.html b/playground/router-with-tests/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router-with-tests/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router-with-tests/jsconfig.json b/playground/router-with-tests/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router-with-tests/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router-with-tests/package.json b/playground/router-with-tests/package.json new file mode 100644 index 000000000..245c5e19a --- /dev/null +++ b/playground/router-with-tests/package.json @@ -0,0 +1,27 @@ +{ + "name": "router-with-tests", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "start-server-and-test": "^2.0.3", + "vite": "^5.0.11", + "vitest": "^1.2.2" + } +} diff --git a/playground/router-with-tests/public/favicon.ico b/playground/router-with-tests/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router-with-tests/src/App.vue b/playground/router-with-tests/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router-with-tests/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router-with-tests/src/assets/logo.svg b/playground/router-with-tests/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router-with-tests/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router-with-tests/src/assets/main.css b/playground/router-with-tests/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router-with-tests/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router-with-tests/src/components/__tests__/HelloWorld.spec.js b/playground/router-with-tests/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/router-with-tests/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/router-with-tests/src/main.js b/playground/router-with-tests/src/main.js new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/router-with-tests/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/router-with-tests/src/router/index.js b/playground/router-with-tests/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router-with-tests/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router-with-tests/src/views/Home.vue b/playground/router-with-tests/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router-with-tests/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router-with-tests/vite.config.js b/playground/router-with-tests/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/router-with-tests/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/router-with-tests/vitest.config.js b/playground/router-with-tests/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/router-with-tests/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/router/.gitignore b/playground/router/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/router/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/router/README.md b/playground/router/README.md new file mode 100644 index 000000000..333dacc65 --- /dev/null +++ b/playground/router/README.md @@ -0,0 +1,29 @@ +# router + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` diff --git a/playground/router/index.html b/playground/router/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/router/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/router/jsconfig.json b/playground/router/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/router/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/router/package.json b/playground/router/package.json new file mode 100644 index 000000000..539aa5b70 --- /dev/null +++ b/playground/router/package.json @@ -0,0 +1,19 @@ +{ + "name": "router", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "vite": "^5.0.11" + } +} diff --git a/playground/router/public/favicon.ico b/playground/router/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/router/src/App.vue b/playground/router/src/App.vue new file mode 100644 index 000000000..fe04cd22e --- /dev/null +++ b/playground/router/src/App.vue @@ -0,0 +1,11 @@ + + + + + diff --git a/playground/router/src/assets/logo.svg b/playground/router/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/router/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/router/src/assets/main.css b/playground/router/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/router/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/router/src/main.js b/playground/router/src/main.js new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/router/src/main.js @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/router/src/router/index.js b/playground/router/src/router/index.js new file mode 100644 index 000000000..68fb92fbe --- /dev/null +++ b/playground/router/src/router/index.js @@ -0,0 +1,15 @@ +import { createRouter, createWebHistory } from 'vue-router' + + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: () => import('../views/Home.vue'), + }, + ] +}) + +export default router diff --git a/playground/router/src/views/Home.vue b/playground/router/src/views/Home.vue new file mode 100644 index 000000000..7bad34e5e --- /dev/null +++ b/playground/router/src/views/Home.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/router/vite.config.js b/playground/router/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/router/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-cypress/.gitignore b/playground/typescript-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-cypress/README.md b/playground/typescript-cypress/README.md new file mode 100644 index 000000000..48f0f894a --- /dev/null +++ b/playground/typescript-cypress/README.md @@ -0,0 +1,62 @@ +# typescript-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Headed Component Tests with [Cypress Component Testing](https://on.cypress.io/component) + +```sh +pnpm test:unit:dev # or `pnpm test:unit` for headless testing +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-cypress/cypress.config.ts b/playground/typescript-cypress/cypress.config.ts new file mode 100644 index 000000000..c8fac1298 --- /dev/null +++ b/playground/typescript-cypress/cypress.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + }, + component: { + specPattern: 'src/**/__tests__/*.{cy,spec}.{js,ts,jsx,tsx}', + devServer: { + framework: 'vue', + bundler: 'vite' + } + } +}) diff --git a/playground/typescript-cypress/cypress/e2e/example.cy.ts b/playground/typescript-cypress/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-cypress/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-cypress/cypress/e2e/tsconfig.json b/playground/typescript-cypress/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-cypress/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-cypress/cypress/fixtures/example.json b/playground/typescript-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-cypress/cypress/support/commands.ts b/playground/typescript-cypress/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-cypress/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-cypress/cypress/support/component-index.html b/playground/typescript-cypress/cypress/support/component-index.html new file mode 100644 index 000000000..5f9622ae2 --- /dev/null +++ b/playground/typescript-cypress/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + Components App + + +
+ + diff --git a/playground/typescript-cypress/cypress/support/component.ts b/playground/typescript-cypress/cypress/support/component.ts new file mode 100644 index 000000000..04e4c352b --- /dev/null +++ b/playground/typescript-cypress/cypress/support/component.ts @@ -0,0 +1,43 @@ +// *********************************************************** +// This example support/component.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') + +// Import global styles +import '@/assets/main.css' + +import { mount } from 'cypress/vue' + +// Augment the Cypress namespace to include type definitions for +// your custom command. +// Alternatively, can be defined in cypress/support/component.d.ts +// with a at the top of your spec. +/* eslint-disable @typescript-eslint/no-namespace */ +declare global { + namespace Cypress { + interface Chainable { + mount: typeof mount + } + } +} + +Cypress.Commands.add('mount', mount) + +// Example use: +// cy.mount(MyComponent) diff --git a/playground/typescript-cypress/cypress/support/e2e.ts b/playground/typescript-cypress/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-cypress/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-cypress/env.d.ts b/playground/typescript-cypress/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-cypress/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-cypress/index.html b/playground/typescript-cypress/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-cypress/package.json b/playground/typescript-cypress/package.json new file mode 100644 index 000000000..ff9e4c1b6 --- /dev/null +++ b/playground/typescript-cypress/package.json @@ -0,0 +1,32 @@ +{ + "name": "typescript-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "test:unit": "cypress run --component", + "test:unit:dev": "cypress open --component", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-cypress/public/favicon.ico b/playground/typescript-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-cypress/src/App.vue b/playground/typescript-cypress/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-cypress/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-cypress/src/assets/logo.svg b/playground/typescript-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-cypress/src/assets/main.css b/playground/typescript-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-cypress/src/components/__tests__/HelloWorld.cy.ts b/playground/typescript-cypress/src/components/__tests__/HelloWorld.cy.ts new file mode 100644 index 000000000..535a0e51c --- /dev/null +++ b/playground/typescript-cypress/src/components/__tests__/HelloWorld.cy.ts @@ -0,0 +1,12 @@ +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('playground', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + }) + + it('renders properly', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + cy.get('h1').should('contain', 'Hello Cypress') + }) +}) diff --git a/playground/typescript-cypress/src/main.ts b/playground/typescript-cypress/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript-cypress/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript-cypress/tsconfig.app.json b/playground/typescript-cypress/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-cypress/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-cypress/tsconfig.cypress-ct.json b/playground/typescript-cypress/tsconfig.cypress-ct.json new file mode 100644 index 000000000..12833b275 --- /dev/null +++ b/playground/typescript-cypress/tsconfig.cypress-ct.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.app.json", + "include": [ + "env.d.ts", + "src/**/*", + "src/**/*.vue", + "cypress/support/component.*", + "cypress/support/commands.ts" + ], + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.cypress-ct.tsbuildinfo" + } +} diff --git a/playground/typescript-cypress/tsconfig.json b/playground/typescript-cypress/tsconfig.json new file mode 100644 index 000000000..d3b6c3172 --- /dev/null +++ b/playground/typescript-cypress/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.cypress-ct.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-cypress/tsconfig.node.json b/playground/typescript-cypress/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-cypress/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-cypress/vite.config.ts b/playground/typescript-cypress/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-cypress/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-cypress/.gitignore b/playground/typescript-jsx-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-cypress/README.md b/playground/typescript-jsx-cypress/README.md new file mode 100644 index 000000000..9dba742fd --- /dev/null +++ b/playground/typescript-jsx-cypress/README.md @@ -0,0 +1,62 @@ +# typescript-jsx-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Headed Component Tests with [Cypress Component Testing](https://on.cypress.io/component) + +```sh +pnpm test:unit:dev # or `pnpm test:unit` for headless testing +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-jsx-cypress/cypress.config.ts b/playground/typescript-jsx-cypress/cypress.config.ts new file mode 100644 index 000000000..c8fac1298 --- /dev/null +++ b/playground/typescript-jsx-cypress/cypress.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + }, + component: { + specPattern: 'src/**/__tests__/*.{cy,spec}.{js,ts,jsx,tsx}', + devServer: { + framework: 'vue', + bundler: 'vite' + } + } +}) diff --git a/playground/typescript-jsx-cypress/cypress/e2e/example.cy.ts b/playground/typescript-jsx-cypress/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-jsx-cypress/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-jsx-cypress/cypress/e2e/tsconfig.json b/playground/typescript-jsx-cypress/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-jsx-cypress/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-jsx-cypress/cypress/fixtures/example.json b/playground/typescript-jsx-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-jsx-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-jsx-cypress/cypress/support/commands.ts b/playground/typescript-jsx-cypress/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-jsx-cypress/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-jsx-cypress/cypress/support/component-index.html b/playground/typescript-jsx-cypress/cypress/support/component-index.html new file mode 100644 index 000000000..5f9622ae2 --- /dev/null +++ b/playground/typescript-jsx-cypress/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + Components App + + +
+ + diff --git a/playground/typescript-jsx-cypress/cypress/support/component.ts b/playground/typescript-jsx-cypress/cypress/support/component.ts new file mode 100644 index 000000000..04e4c352b --- /dev/null +++ b/playground/typescript-jsx-cypress/cypress/support/component.ts @@ -0,0 +1,43 @@ +// *********************************************************** +// This example support/component.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') + +// Import global styles +import '@/assets/main.css' + +import { mount } from 'cypress/vue' + +// Augment the Cypress namespace to include type definitions for +// your custom command. +// Alternatively, can be defined in cypress/support/component.d.ts +// with a at the top of your spec. +/* eslint-disable @typescript-eslint/no-namespace */ +declare global { + namespace Cypress { + interface Chainable { + mount: typeof mount + } + } +} + +Cypress.Commands.add('mount', mount) + +// Example use: +// cy.mount(MyComponent) diff --git a/playground/typescript-jsx-cypress/cypress/support/e2e.ts b/playground/typescript-jsx-cypress/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-jsx-cypress/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-jsx-cypress/env.d.ts b/playground/typescript-jsx-cypress/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-cypress/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-cypress/index.html b/playground/typescript-jsx-cypress/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-cypress/package.json b/playground/typescript-jsx-cypress/package.json new file mode 100644 index 000000000..7e2003a78 --- /dev/null +++ b/playground/typescript-jsx-cypress/package.json @@ -0,0 +1,33 @@ +{ + "name": "typescript-jsx-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "test:unit": "cypress run --component", + "test:unit:dev": "cypress open --component", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-cypress/public/favicon.ico b/playground/typescript-jsx-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-cypress/src/App.vue b/playground/typescript-jsx-cypress/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx-cypress/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx-cypress/src/assets/logo.svg b/playground/typescript-jsx-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-cypress/src/assets/main.css b/playground/typescript-jsx-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-cypress/src/components/__tests__/HelloWorld.cy.ts b/playground/typescript-jsx-cypress/src/components/__tests__/HelloWorld.cy.ts new file mode 100644 index 000000000..535a0e51c --- /dev/null +++ b/playground/typescript-jsx-cypress/src/components/__tests__/HelloWorld.cy.ts @@ -0,0 +1,12 @@ +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('playground', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + }) + + it('renders properly', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + cy.get('h1').should('contain', 'Hello Cypress') + }) +}) diff --git a/playground/typescript-jsx-cypress/src/main.ts b/playground/typescript-jsx-cypress/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript-jsx-cypress/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript-jsx-cypress/tsconfig.app.json b/playground/typescript-jsx-cypress/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-cypress/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-cypress/tsconfig.cypress-ct.json b/playground/typescript-jsx-cypress/tsconfig.cypress-ct.json new file mode 100644 index 000000000..12833b275 --- /dev/null +++ b/playground/typescript-jsx-cypress/tsconfig.cypress-ct.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.app.json", + "include": [ + "env.d.ts", + "src/**/*", + "src/**/*.vue", + "cypress/support/component.*", + "cypress/support/commands.ts" + ], + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.cypress-ct.tsbuildinfo" + } +} diff --git a/playground/typescript-jsx-cypress/tsconfig.json b/playground/typescript-jsx-cypress/tsconfig.json new file mode 100644 index 000000000..d3b6c3172 --- /dev/null +++ b/playground/typescript-jsx-cypress/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.cypress-ct.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-jsx-cypress/tsconfig.node.json b/playground/typescript-jsx-cypress/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-cypress/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-cypress/vite.config.ts b/playground/typescript-jsx-cypress/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-cypress/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-nightwatch/.gitignore b/playground/typescript-jsx-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/typescript-jsx-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/typescript-jsx-nightwatch/.vscode/extensions.json b/playground/typescript-jsx-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/typescript-jsx-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/typescript-jsx-nightwatch/README.md b/playground/typescript-jsx-nightwatch/README.md new file mode 100644 index 000000000..9b881c035 --- /dev/null +++ b/playground/typescript-jsx-nightwatch/README.md @@ -0,0 +1,63 @@ +# typescript-jsx-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/typescript-jsx-nightwatch/env.d.ts b/playground/typescript-jsx-nightwatch/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-nightwatch/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-nightwatch/index.html b/playground/typescript-jsx-nightwatch/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-nightwatch/nightwatch.conf.cjs b/playground/typescript-jsx-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/typescript-jsx-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/typescript-jsx-nightwatch/nightwatch/index.html b/playground/typescript-jsx-nightwatch/nightwatch/index.html new file mode 100644 index 000000000..b7e1ec765 --- /dev/null +++ b/playground/typescript-jsx-nightwatch/nightwatch/index.html @@ -0,0 +1,16 @@ + + + + + + + + + Vue Renderer + + + +
+ + + diff --git a/playground/typescript-jsx-nightwatch/nightwatch/nightwatch.d.ts b/playground/typescript-jsx-nightwatch/nightwatch/nightwatch.d.ts new file mode 100644 index 000000000..616e63f9f --- /dev/null +++ b/playground/typescript-jsx-nightwatch/nightwatch/nightwatch.d.ts @@ -0,0 +1,13 @@ +import { NightwatchCustomAssertions, NightwatchCustomCommands } from 'nightwatch' + +declare module 'nightwatch' { + interface NightwatchCustomAssertions { + // Add your custom assertions' types here + // elementHasCount: (selector: string, count: number) => NightwatchBrowser + } + + interface NightwatchCustomCommands { + // Add your custom commands' types here + // strictClick: (selector: string) => NightwatchBrowser + } +} diff --git a/playground/typescript-jsx-nightwatch/nightwatch/tsconfig.json b/playground/typescript-jsx-nightwatch/nightwatch/tsconfig.json new file mode 100644 index 000000000..8cd7ca1da --- /dev/null +++ b/playground/typescript-jsx-nightwatch/nightwatch/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "../node_modules/.tmp/tsconfig.nightwatch.tsbuildinfo", + + "target": "ESNext", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": "../", + "lib": ["ESNext", "dom"], + "types": ["nightwatch"] + }, + "include": ["../node_modules/@nightwatch/**/*", "../src/components/**/*", "../tests/e2e/**/*"], + "ts-node": { + "transpileOnly": true + }, + "files": ["nightwatch.d.ts"] +} diff --git a/playground/typescript-jsx-nightwatch/package.json b/playground/typescript-jsx-nightwatch/package.json new file mode 100644 index 000000000..8a948f24a --- /dev/null +++ b/playground/typescript-jsx-nightwatch/package.json @@ -0,0 +1,36 @@ +{ + "name": "typescript-jsx-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "nightwatch tests/e2e/*", + "test:unit": "nightwatch src/**/__tests__/*", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "nightwatch": "^3.4.0", + "npm-run-all2": "^6.1.2", + "ts-node": "^10.9.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-nightwatch/public/favicon.ico b/playground/typescript-jsx-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-nightwatch/src/App.vue b/playground/typescript-jsx-nightwatch/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx-nightwatch/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx-nightwatch/src/assets/logo.svg b/playground/typescript-jsx-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-nightwatch/src/assets/main.css b/playground/typescript-jsx-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-nightwatch/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-nightwatch/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..810641e6e --- /dev/null +++ b/playground/typescript-jsx-nightwatch/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,14 @@ +describe('Hello World', function () { + before((browser) => { + browser.init() + }) + + it('renders properly', async function () { + const welcomeComponent = await browser.mountComponent('/src/components/HelloWorld.vue', {props: {msg: 'Hello Nightwatch'}}); + + browser.expect.element(welcomeComponent).to.be.present; + browser.expect.element('h1').text.to.contain('Hello Nightwatch'); + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-jsx-nightwatch/src/main.ts b/playground/typescript-jsx-nightwatch/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript-jsx-nightwatch/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript-jsx-nightwatch/tests/e2e/example.ts b/playground/typescript-jsx-nightwatch/tests/e2e/example.ts new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/typescript-jsx-nightwatch/tests/e2e/example.ts @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-jsx-nightwatch/tsconfig.app.json b/playground/typescript-jsx-nightwatch/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-nightwatch/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-nightwatch/tsconfig.json b/playground/typescript-jsx-nightwatch/tsconfig.json new file mode 100644 index 000000000..5c385ae2c --- /dev/null +++ b/playground/typescript-jsx-nightwatch/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./nightwatch/tsconfig.json" + } + ] +} diff --git a/playground/typescript-jsx-nightwatch/tsconfig.node.json b/playground/typescript-jsx-nightwatch/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-nightwatch/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-nightwatch/vite.config.ts b/playground/typescript-jsx-nightwatch/vite.config.ts new file mode 100644 index 000000000..3e49bf0ca --- /dev/null +++ b/playground/typescript-jsx-nightwatch/vite.config.ts @@ -0,0 +1,22 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + nightwatchPlugin({ + renderPage: './nightwatch/index.html' + }), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-pinia-cypress/.gitignore b/playground/typescript-jsx-pinia-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-pinia-cypress/README.md b/playground/typescript-jsx-pinia-cypress/README.md new file mode 100644 index 000000000..35cce24d5 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/README.md @@ -0,0 +1,62 @@ +# typescript-jsx-pinia-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Headed Component Tests with [Cypress Component Testing](https://on.cypress.io/component) + +```sh +pnpm test:unit:dev # or `pnpm test:unit` for headless testing +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-jsx-pinia-cypress/cypress.config.ts b/playground/typescript-jsx-pinia-cypress/cypress.config.ts new file mode 100644 index 000000000..c8fac1298 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/cypress.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + }, + component: { + specPattern: 'src/**/__tests__/*.{cy,spec}.{js,ts,jsx,tsx}', + devServer: { + framework: 'vue', + bundler: 'vite' + } + } +}) diff --git a/playground/typescript-jsx-pinia-cypress/cypress/e2e/example.cy.ts b/playground/typescript-jsx-pinia-cypress/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-jsx-pinia-cypress/cypress/e2e/tsconfig.json b/playground/typescript-jsx-pinia-cypress/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-jsx-pinia-cypress/cypress/fixtures/example.json b/playground/typescript-jsx-pinia-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-jsx-pinia-cypress/cypress/support/commands.ts b/playground/typescript-jsx-pinia-cypress/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-jsx-pinia-cypress/cypress/support/component-index.html b/playground/typescript-jsx-pinia-cypress/cypress/support/component-index.html new file mode 100644 index 000000000..5f9622ae2 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + Components App + + +
+ + diff --git a/playground/typescript-jsx-pinia-cypress/cypress/support/component.ts b/playground/typescript-jsx-pinia-cypress/cypress/support/component.ts new file mode 100644 index 000000000..04e4c352b --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/cypress/support/component.ts @@ -0,0 +1,43 @@ +// *********************************************************** +// This example support/component.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') + +// Import global styles +import '@/assets/main.css' + +import { mount } from 'cypress/vue' + +// Augment the Cypress namespace to include type definitions for +// your custom command. +// Alternatively, can be defined in cypress/support/component.d.ts +// with a at the top of your spec. +/* eslint-disable @typescript-eslint/no-namespace */ +declare global { + namespace Cypress { + interface Chainable { + mount: typeof mount + } + } +} + +Cypress.Commands.add('mount', mount) + +// Example use: +// cy.mount(MyComponent) diff --git a/playground/typescript-jsx-pinia-cypress/cypress/support/e2e.ts b/playground/typescript-jsx-pinia-cypress/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-jsx-pinia-cypress/env.d.ts b/playground/typescript-jsx-pinia-cypress/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-pinia-cypress/index.html b/playground/typescript-jsx-pinia-cypress/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-pinia-cypress/package.json b/playground/typescript-jsx-pinia-cypress/package.json new file mode 100644 index 000000000..410635bc7 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/package.json @@ -0,0 +1,34 @@ +{ + "name": "typescript-jsx-pinia-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "test:unit": "cypress run --component", + "test:unit:dev": "cypress open --component", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-pinia-cypress/public/favicon.ico b/playground/typescript-jsx-pinia-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-pinia-cypress/src/App.vue b/playground/typescript-jsx-pinia-cypress/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx-pinia-cypress/src/assets/logo.svg b/playground/typescript-jsx-pinia-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-pinia-cypress/src/assets/main.css b/playground/typescript-jsx-pinia-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-pinia-cypress/src/components/__tests__/HelloWorld.cy.ts b/playground/typescript-jsx-pinia-cypress/src/components/__tests__/HelloWorld.cy.ts new file mode 100644 index 000000000..535a0e51c --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/src/components/__tests__/HelloWorld.cy.ts @@ -0,0 +1,12 @@ +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('playground', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + }) + + it('renders properly', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + cy.get('h1').should('contain', 'Hello Cypress') + }) +}) diff --git a/playground/typescript-jsx-pinia-cypress/src/main.ts b/playground/typescript-jsx-pinia-cypress/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-jsx-pinia-cypress/src/stores/counter.ts b/playground/typescript-jsx-pinia-cypress/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-pinia-cypress/tsconfig.app.json b/playground/typescript-jsx-pinia-cypress/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-pinia-cypress/tsconfig.cypress-ct.json b/playground/typescript-jsx-pinia-cypress/tsconfig.cypress-ct.json new file mode 100644 index 000000000..12833b275 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/tsconfig.cypress-ct.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.app.json", + "include": [ + "env.d.ts", + "src/**/*", + "src/**/*.vue", + "cypress/support/component.*", + "cypress/support/commands.ts" + ], + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.cypress-ct.tsbuildinfo" + } +} diff --git a/playground/typescript-jsx-pinia-cypress/tsconfig.json b/playground/typescript-jsx-pinia-cypress/tsconfig.json new file mode 100644 index 000000000..d3b6c3172 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.cypress-ct.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-jsx-pinia-cypress/tsconfig.node.json b/playground/typescript-jsx-pinia-cypress/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-pinia-cypress/vite.config.ts b/playground/typescript-jsx-pinia-cypress/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-pinia-cypress/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-pinia-nightwatch/.gitignore b/playground/typescript-jsx-pinia-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/typescript-jsx-pinia-nightwatch/.vscode/extensions.json b/playground/typescript-jsx-pinia-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/typescript-jsx-pinia-nightwatch/README.md b/playground/typescript-jsx-pinia-nightwatch/README.md new file mode 100644 index 000000000..d5692ffb4 --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/README.md @@ -0,0 +1,63 @@ +# typescript-jsx-pinia-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/typescript-jsx-pinia-nightwatch/env.d.ts b/playground/typescript-jsx-pinia-nightwatch/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-pinia-nightwatch/index.html b/playground/typescript-jsx-pinia-nightwatch/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-pinia-nightwatch/nightwatch.conf.cjs b/playground/typescript-jsx-pinia-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/typescript-jsx-pinia-nightwatch/nightwatch/index.html b/playground/typescript-jsx-pinia-nightwatch/nightwatch/index.html new file mode 100644 index 000000000..b7e1ec765 --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/nightwatch/index.html @@ -0,0 +1,16 @@ + + + + + + + + + Vue Renderer + + + +
+ + + diff --git a/playground/typescript-jsx-pinia-nightwatch/nightwatch/nightwatch.d.ts b/playground/typescript-jsx-pinia-nightwatch/nightwatch/nightwatch.d.ts new file mode 100644 index 000000000..616e63f9f --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/nightwatch/nightwatch.d.ts @@ -0,0 +1,13 @@ +import { NightwatchCustomAssertions, NightwatchCustomCommands } from 'nightwatch' + +declare module 'nightwatch' { + interface NightwatchCustomAssertions { + // Add your custom assertions' types here + // elementHasCount: (selector: string, count: number) => NightwatchBrowser + } + + interface NightwatchCustomCommands { + // Add your custom commands' types here + // strictClick: (selector: string) => NightwatchBrowser + } +} diff --git a/playground/typescript-jsx-pinia-nightwatch/nightwatch/tsconfig.json b/playground/typescript-jsx-pinia-nightwatch/nightwatch/tsconfig.json new file mode 100644 index 000000000..8cd7ca1da --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/nightwatch/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "../node_modules/.tmp/tsconfig.nightwatch.tsbuildinfo", + + "target": "ESNext", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": "../", + "lib": ["ESNext", "dom"], + "types": ["nightwatch"] + }, + "include": ["../node_modules/@nightwatch/**/*", "../src/components/**/*", "../tests/e2e/**/*"], + "ts-node": { + "transpileOnly": true + }, + "files": ["nightwatch.d.ts"] +} diff --git a/playground/typescript-jsx-pinia-nightwatch/package.json b/playground/typescript-jsx-pinia-nightwatch/package.json new file mode 100644 index 000000000..e317289b3 --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/package.json @@ -0,0 +1,37 @@ +{ + "name": "typescript-jsx-pinia-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "nightwatch tests/e2e/*", + "test:unit": "nightwatch src/**/__tests__/*", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "nightwatch": "^3.4.0", + "npm-run-all2": "^6.1.2", + "ts-node": "^10.9.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-pinia-nightwatch/public/favicon.ico b/playground/typescript-jsx-pinia-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-pinia-nightwatch/src/App.vue b/playground/typescript-jsx-pinia-nightwatch/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx-pinia-nightwatch/src/assets/logo.svg b/playground/typescript-jsx-pinia-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-pinia-nightwatch/src/assets/main.css b/playground/typescript-jsx-pinia-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..810641e6e --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,14 @@ +describe('Hello World', function () { + before((browser) => { + browser.init() + }) + + it('renders properly', async function () { + const welcomeComponent = await browser.mountComponent('/src/components/HelloWorld.vue', {props: {msg: 'Hello Nightwatch'}}); + + browser.expect.element(welcomeComponent).to.be.present; + browser.expect.element('h1').text.to.contain('Hello Nightwatch'); + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-jsx-pinia-nightwatch/src/main.ts b/playground/typescript-jsx-pinia-nightwatch/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-jsx-pinia-nightwatch/src/stores/counter.ts b/playground/typescript-jsx-pinia-nightwatch/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-pinia-nightwatch/tests/e2e/example.ts b/playground/typescript-jsx-pinia-nightwatch/tests/e2e/example.ts new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/tests/e2e/example.ts @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-jsx-pinia-nightwatch/tsconfig.app.json b/playground/typescript-jsx-pinia-nightwatch/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-pinia-nightwatch/tsconfig.json b/playground/typescript-jsx-pinia-nightwatch/tsconfig.json new file mode 100644 index 000000000..5c385ae2c --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./nightwatch/tsconfig.json" + } + ] +} diff --git a/playground/typescript-jsx-pinia-nightwatch/tsconfig.node.json b/playground/typescript-jsx-pinia-nightwatch/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-pinia-nightwatch/vite.config.ts b/playground/typescript-jsx-pinia-nightwatch/vite.config.ts new file mode 100644 index 000000000..3e49bf0ca --- /dev/null +++ b/playground/typescript-jsx-pinia-nightwatch/vite.config.ts @@ -0,0 +1,22 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + nightwatchPlugin({ + renderPage: './nightwatch/index.html' + }), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-pinia-playwright/.gitignore b/playground/typescript-jsx-pinia-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/typescript-jsx-pinia-playwright/.vscode/extensions.json b/playground/typescript-jsx-pinia-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/typescript-jsx-pinia-playwright/README.md b/playground/typescript-jsx-pinia-playwright/README.md new file mode 100644 index 000000000..11d7f3039 --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/README.md @@ -0,0 +1,59 @@ +# typescript-jsx-pinia-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/typescript-jsx-pinia-playwright/e2e/tsconfig.json b/playground/typescript-jsx-pinia-playwright/e2e/tsconfig.json new file mode 100644 index 000000000..be3bbfc0e --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": ["./**/*"] +} diff --git a/playground/typescript-jsx-pinia-playwright/e2e/vue.spec.ts b/playground/typescript-jsx-pinia-playwright/e2e/vue.spec.ts new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/e2e/vue.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/typescript-jsx-pinia-playwright/env.d.ts b/playground/typescript-jsx-pinia-playwright/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-pinia-playwright/index.html b/playground/typescript-jsx-pinia-playwright/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-pinia-playwright/package.json b/playground/typescript-jsx-pinia-playwright/package.json new file mode 100644 index 000000000..389c38dd6 --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/package.json @@ -0,0 +1,30 @@ +{ + "name": "typescript-jsx-pinia-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "playwright test", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-pinia-playwright/playwright.config.ts b/playground/typescript-jsx-pinia-playwright/playwright.config.ts new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/playwright.config.ts @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/typescript-jsx-pinia-playwright/public/favicon.ico b/playground/typescript-jsx-pinia-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-pinia-playwright/src/App.vue b/playground/typescript-jsx-pinia-playwright/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx-pinia-playwright/src/assets/logo.svg b/playground/typescript-jsx-pinia-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-pinia-playwright/src/assets/main.css b/playground/typescript-jsx-pinia-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-pinia-playwright/src/main.ts b/playground/typescript-jsx-pinia-playwright/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-jsx-pinia-playwright/src/stores/counter.ts b/playground/typescript-jsx-pinia-playwright/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-pinia-playwright/tsconfig.app.json b/playground/typescript-jsx-pinia-playwright/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-pinia-playwright/tsconfig.json b/playground/typescript-jsx-pinia-playwright/tsconfig.json new file mode 100644 index 000000000..66b5e5703 --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/playground/typescript-jsx-pinia-playwright/tsconfig.node.json b/playground/typescript-jsx-pinia-playwright/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-pinia-playwright/vite.config.ts b/playground/typescript-jsx-pinia-playwright/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-pinia-playwright/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-pinia-vitest-cypress/.gitignore b/playground/typescript-jsx-pinia-vitest-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-pinia-vitest-cypress/README.md b/playground/typescript-jsx-pinia-vitest-cypress/README.md new file mode 100644 index 000000000..fd81efc33 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/README.md @@ -0,0 +1,62 @@ +# typescript-jsx-pinia-vitest-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-jsx-pinia-vitest-cypress/cypress.config.ts b/playground/typescript-jsx-pinia-vitest-cypress/cypress.config.ts new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/cypress.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/typescript-jsx-pinia-vitest-cypress/cypress/e2e/example.cy.ts b/playground/typescript-jsx-pinia-vitest-cypress/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-jsx-pinia-vitest-cypress/cypress/e2e/tsconfig.json b/playground/typescript-jsx-pinia-vitest-cypress/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-jsx-pinia-vitest-cypress/cypress/fixtures/example.json b/playground/typescript-jsx-pinia-vitest-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-jsx-pinia-vitest-cypress/cypress/support/commands.ts b/playground/typescript-jsx-pinia-vitest-cypress/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-jsx-pinia-vitest-cypress/cypress/support/e2e.ts b/playground/typescript-jsx-pinia-vitest-cypress/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-jsx-pinia-vitest-cypress/env.d.ts b/playground/typescript-jsx-pinia-vitest-cypress/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-pinia-vitest-cypress/index.html b/playground/typescript-jsx-pinia-vitest-cypress/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-pinia-vitest-cypress/package.json b/playground/typescript-jsx-pinia-vitest-cypress/package.json new file mode 100644 index 000000000..6728f52ca --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/package.json @@ -0,0 +1,37 @@ +{ + "name": "typescript-jsx-pinia-vitest-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-pinia-vitest-cypress/public/favicon.ico b/playground/typescript-jsx-pinia-vitest-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-pinia-vitest-cypress/src/App.vue b/playground/typescript-jsx-pinia-vitest-cypress/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx-pinia-vitest-cypress/src/assets/logo.svg b/playground/typescript-jsx-pinia-vitest-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-pinia-vitest-cypress/src/assets/main.css b/playground/typescript-jsx-pinia-vitest-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-pinia-vitest-cypress/src/main.ts b/playground/typescript-jsx-pinia-vitest-cypress/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-jsx-pinia-vitest-cypress/src/stores/counter.ts b/playground/typescript-jsx-pinia-vitest-cypress/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-pinia-vitest-cypress/tsconfig.app.json b/playground/typescript-jsx-pinia-vitest-cypress/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-pinia-vitest-cypress/tsconfig.json b/playground/typescript-jsx-pinia-vitest-cypress/tsconfig.json new file mode 100644 index 000000000..5304731b8 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-jsx-pinia-vitest-cypress/tsconfig.node.json b/playground/typescript-jsx-pinia-vitest-cypress/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-pinia-vitest-cypress/tsconfig.vitest.json b/playground/typescript-jsx-pinia-vitest-cypress/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-pinia-vitest-cypress/vite.config.ts b/playground/typescript-jsx-pinia-vitest-cypress/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-pinia-vitest-cypress/vitest.config.ts b/playground/typescript-jsx-pinia-vitest-cypress/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-cypress/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/.gitignore b/playground/typescript-jsx-pinia-vitest-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/.vscode/extensions.json b/playground/typescript-jsx-pinia-vitest-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/README.md b/playground/typescript-jsx-pinia-vitest-nightwatch/README.md new file mode 100644 index 000000000..98c934139 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/README.md @@ -0,0 +1,69 @@ +# typescript-jsx-pinia-vitest-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/env.d.ts b/playground/typescript-jsx-pinia-vitest-nightwatch/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/index.html b/playground/typescript-jsx-pinia-vitest-nightwatch/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/nightwatch.conf.cjs b/playground/typescript-jsx-pinia-vitest-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/nightwatch/nightwatch.d.ts b/playground/typescript-jsx-pinia-vitest-nightwatch/nightwatch/nightwatch.d.ts new file mode 100644 index 000000000..616e63f9f --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/nightwatch/nightwatch.d.ts @@ -0,0 +1,13 @@ +import { NightwatchCustomAssertions, NightwatchCustomCommands } from 'nightwatch' + +declare module 'nightwatch' { + interface NightwatchCustomAssertions { + // Add your custom assertions' types here + // elementHasCount: (selector: string, count: number) => NightwatchBrowser + } + + interface NightwatchCustomCommands { + // Add your custom commands' types here + // strictClick: (selector: string) => NightwatchBrowser + } +} diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/nightwatch/tsconfig.json b/playground/typescript-jsx-pinia-vitest-nightwatch/nightwatch/tsconfig.json new file mode 100644 index 000000000..8cd7ca1da --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/nightwatch/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "../node_modules/.tmp/tsconfig.nightwatch.tsbuildinfo", + + "target": "ESNext", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": "../", + "lib": ["ESNext", "dom"], + "types": ["nightwatch"] + }, + "include": ["../node_modules/@nightwatch/**/*", "../src/components/**/*", "../tests/e2e/**/*"], + "ts-node": { + "transpileOnly": true + }, + "files": ["nightwatch.d.ts"] +} diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/package.json b/playground/typescript-jsx-pinia-vitest-nightwatch/package.json new file mode 100644 index 000000000..86398b6b1 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/package.json @@ -0,0 +1,40 @@ +{ + "name": "typescript-jsx-pinia-vitest-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "nightwatch tests/e2e/*", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "jsdom": "^24.0.0", + "nightwatch": "^3.4.0", + "npm-run-all2": "^6.1.2", + "ts-node": "^10.9.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/public/favicon.ico b/playground/typescript-jsx-pinia-vitest-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/src/App.vue b/playground/typescript-jsx-pinia-vitest-nightwatch/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/src/assets/logo.svg b/playground/typescript-jsx-pinia-vitest-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/src/assets/main.css b/playground/typescript-jsx-pinia-vitest-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/src/main.ts b/playground/typescript-jsx-pinia-vitest-nightwatch/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/src/stores/counter.ts b/playground/typescript-jsx-pinia-vitest-nightwatch/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/tests/e2e/example.ts b/playground/typescript-jsx-pinia-vitest-nightwatch/tests/e2e/example.ts new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/tests/e2e/example.ts @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/tsconfig.app.json b/playground/typescript-jsx-pinia-vitest-nightwatch/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/tsconfig.json b/playground/typescript-jsx-pinia-vitest-nightwatch/tsconfig.json new file mode 100644 index 000000000..a5352e667 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + }, + { + "path": "./nightwatch/tsconfig.json" + } + ] +} diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/tsconfig.node.json b/playground/typescript-jsx-pinia-vitest-nightwatch/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/tsconfig.vitest.json b/playground/typescript-jsx-pinia-vitest-nightwatch/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/vite.config.ts b/playground/typescript-jsx-pinia-vitest-nightwatch/vite.config.ts new file mode 100644 index 000000000..3a6988230 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/vite.config.ts @@ -0,0 +1,20 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + nightwatchPlugin(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-pinia-vitest-nightwatch/vitest.config.ts b/playground/typescript-jsx-pinia-vitest-nightwatch/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-nightwatch/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-pinia-vitest-playwright/.gitignore b/playground/typescript-jsx-pinia-vitest-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/typescript-jsx-pinia-vitest-playwright/.vscode/extensions.json b/playground/typescript-jsx-pinia-vitest-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/typescript-jsx-pinia-vitest-playwright/README.md b/playground/typescript-jsx-pinia-vitest-playwright/README.md new file mode 100644 index 000000000..741e22988 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/README.md @@ -0,0 +1,65 @@ +# typescript-jsx-pinia-vitest-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/typescript-jsx-pinia-vitest-playwright/e2e/tsconfig.json b/playground/typescript-jsx-pinia-vitest-playwright/e2e/tsconfig.json new file mode 100644 index 000000000..be3bbfc0e --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": ["./**/*"] +} diff --git a/playground/typescript-jsx-pinia-vitest-playwright/e2e/vue.spec.ts b/playground/typescript-jsx-pinia-vitest-playwright/e2e/vue.spec.ts new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/e2e/vue.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/typescript-jsx-pinia-vitest-playwright/env.d.ts b/playground/typescript-jsx-pinia-vitest-playwright/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-pinia-vitest-playwright/index.html b/playground/typescript-jsx-pinia-vitest-playwright/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-pinia-vitest-playwright/package.json b/playground/typescript-jsx-pinia-vitest-playwright/package.json new file mode 100644 index 000000000..f722f210f --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/package.json @@ -0,0 +1,35 @@ +{ + "name": "typescript-jsx-pinia-vitest-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "playwright test", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-pinia-vitest-playwright/playwright.config.ts b/playground/typescript-jsx-pinia-vitest-playwright/playwright.config.ts new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/playwright.config.ts @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/typescript-jsx-pinia-vitest-playwright/public/favicon.ico b/playground/typescript-jsx-pinia-vitest-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-pinia-vitest-playwright/src/App.vue b/playground/typescript-jsx-pinia-vitest-playwright/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx-pinia-vitest-playwright/src/assets/logo.svg b/playground/typescript-jsx-pinia-vitest-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-pinia-vitest-playwright/src/assets/main.css b/playground/typescript-jsx-pinia-vitest-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-pinia-vitest-playwright/src/main.ts b/playground/typescript-jsx-pinia-vitest-playwright/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-jsx-pinia-vitest-playwright/src/stores/counter.ts b/playground/typescript-jsx-pinia-vitest-playwright/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-pinia-vitest-playwright/tsconfig.app.json b/playground/typescript-jsx-pinia-vitest-playwright/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-pinia-vitest-playwright/tsconfig.json b/playground/typescript-jsx-pinia-vitest-playwright/tsconfig.json new file mode 100644 index 000000000..100cf6a8f --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ] +} diff --git a/playground/typescript-jsx-pinia-vitest-playwright/tsconfig.node.json b/playground/typescript-jsx-pinia-vitest-playwright/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-pinia-vitest-playwright/tsconfig.vitest.json b/playground/typescript-jsx-pinia-vitest-playwright/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-pinia-vitest-playwright/vite.config.ts b/playground/typescript-jsx-pinia-vitest-playwright/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-pinia-vitest-playwright/vitest.config.ts b/playground/typescript-jsx-pinia-vitest-playwright/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest-playwright/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-pinia-vitest/.gitignore b/playground/typescript-jsx-pinia-vitest/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-pinia-vitest/README.md b/playground/typescript-jsx-pinia-vitest/README.md new file mode 100644 index 000000000..016c52b62 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest/README.md @@ -0,0 +1,46 @@ +# typescript-jsx-pinia-vitest + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` diff --git a/playground/typescript-jsx-pinia-vitest/env.d.ts b/playground/typescript-jsx-pinia-vitest/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-pinia-vitest/index.html b/playground/typescript-jsx-pinia-vitest/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-pinia-vitest/package.json b/playground/typescript-jsx-pinia-vitest/package.json new file mode 100644 index 000000000..f0395d5d5 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest/package.json @@ -0,0 +1,33 @@ +{ + "name": "typescript-jsx-pinia-vitest", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-pinia-vitest/public/favicon.ico b/playground/typescript-jsx-pinia-vitest/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-pinia-vitest/src/App.vue b/playground/typescript-jsx-pinia-vitest/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx-pinia-vitest/src/assets/logo.svg b/playground/typescript-jsx-pinia-vitest/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-pinia-vitest/src/assets/main.css b/playground/typescript-jsx-pinia-vitest/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-pinia-vitest/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-pinia-vitest/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-pinia-vitest/src/main.ts b/playground/typescript-jsx-pinia-vitest/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-jsx-pinia-vitest/src/stores/counter.ts b/playground/typescript-jsx-pinia-vitest/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-pinia-vitest/tsconfig.app.json b/playground/typescript-jsx-pinia-vitest/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-pinia-vitest/tsconfig.json b/playground/typescript-jsx-pinia-vitest/tsconfig.json new file mode 100644 index 000000000..100cf6a8f --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ] +} diff --git a/playground/typescript-jsx-pinia-vitest/tsconfig.node.json b/playground/typescript-jsx-pinia-vitest/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-pinia-vitest/tsconfig.vitest.json b/playground/typescript-jsx-pinia-vitest/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-pinia-vitest/vite.config.ts b/playground/typescript-jsx-pinia-vitest/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-pinia-vitest/vitest.config.ts b/playground/typescript-jsx-pinia-vitest/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-pinia-vitest/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-pinia-with-tests/.gitignore b/playground/typescript-jsx-pinia-with-tests/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-pinia-with-tests/README.md b/playground/typescript-jsx-pinia-with-tests/README.md new file mode 100644 index 000000000..0704f2f8a --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/README.md @@ -0,0 +1,62 @@ +# typescript-jsx-pinia-with-tests + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-jsx-pinia-with-tests/cypress.config.ts b/playground/typescript-jsx-pinia-with-tests/cypress.config.ts new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/cypress.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/typescript-jsx-pinia-with-tests/cypress/e2e/example.cy.ts b/playground/typescript-jsx-pinia-with-tests/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-jsx-pinia-with-tests/cypress/e2e/tsconfig.json b/playground/typescript-jsx-pinia-with-tests/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-jsx-pinia-with-tests/cypress/fixtures/example.json b/playground/typescript-jsx-pinia-with-tests/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-jsx-pinia-with-tests/cypress/support/commands.ts b/playground/typescript-jsx-pinia-with-tests/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-jsx-pinia-with-tests/cypress/support/e2e.ts b/playground/typescript-jsx-pinia-with-tests/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-jsx-pinia-with-tests/env.d.ts b/playground/typescript-jsx-pinia-with-tests/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-pinia-with-tests/index.html b/playground/typescript-jsx-pinia-with-tests/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-pinia-with-tests/package.json b/playground/typescript-jsx-pinia-with-tests/package.json new file mode 100644 index 000000000..98bdd18b8 --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/package.json @@ -0,0 +1,37 @@ +{ + "name": "typescript-jsx-pinia-with-tests", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-pinia-with-tests/public/favicon.ico b/playground/typescript-jsx-pinia-with-tests/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-pinia-with-tests/src/App.vue b/playground/typescript-jsx-pinia-with-tests/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx-pinia-with-tests/src/assets/logo.svg b/playground/typescript-jsx-pinia-with-tests/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-pinia-with-tests/src/assets/main.css b/playground/typescript-jsx-pinia-with-tests/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-pinia-with-tests/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-pinia-with-tests/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-pinia-with-tests/src/main.ts b/playground/typescript-jsx-pinia-with-tests/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-jsx-pinia-with-tests/src/stores/counter.ts b/playground/typescript-jsx-pinia-with-tests/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-pinia-with-tests/tsconfig.app.json b/playground/typescript-jsx-pinia-with-tests/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-pinia-with-tests/tsconfig.json b/playground/typescript-jsx-pinia-with-tests/tsconfig.json new file mode 100644 index 000000000..5304731b8 --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-jsx-pinia-with-tests/tsconfig.node.json b/playground/typescript-jsx-pinia-with-tests/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-pinia-with-tests/tsconfig.vitest.json b/playground/typescript-jsx-pinia-with-tests/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-pinia-with-tests/vite.config.ts b/playground/typescript-jsx-pinia-with-tests/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-pinia-with-tests/vitest.config.ts b/playground/typescript-jsx-pinia-with-tests/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-pinia-with-tests/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-pinia/.gitignore b/playground/typescript-jsx-pinia/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-pinia/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-pinia/README.md b/playground/typescript-jsx-pinia/README.md new file mode 100644 index 000000000..3edce380a --- /dev/null +++ b/playground/typescript-jsx-pinia/README.md @@ -0,0 +1,40 @@ +# typescript-jsx-pinia + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` diff --git a/playground/typescript-jsx-pinia/env.d.ts b/playground/typescript-jsx-pinia/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-pinia/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-pinia/index.html b/playground/typescript-jsx-pinia/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-pinia/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-pinia/package.json b/playground/typescript-jsx-pinia/package.json new file mode 100644 index 000000000..0085409bd --- /dev/null +++ b/playground/typescript-jsx-pinia/package.json @@ -0,0 +1,28 @@ +{ + "name": "typescript-jsx-pinia", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-pinia/public/favicon.ico b/playground/typescript-jsx-pinia/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-pinia/src/App.vue b/playground/typescript-jsx-pinia/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx-pinia/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx-pinia/src/assets/logo.svg b/playground/typescript-jsx-pinia/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-pinia/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-pinia/src/assets/main.css b/playground/typescript-jsx-pinia/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-pinia/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-pinia/src/main.ts b/playground/typescript-jsx-pinia/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-jsx-pinia/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-jsx-pinia/src/stores/counter.ts b/playground/typescript-jsx-pinia/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-pinia/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-pinia/tsconfig.app.json b/playground/typescript-jsx-pinia/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-pinia/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-pinia/tsconfig.json b/playground/typescript-jsx-pinia/tsconfig.json new file mode 100644 index 000000000..66b5e5703 --- /dev/null +++ b/playground/typescript-jsx-pinia/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/playground/typescript-jsx-pinia/tsconfig.node.json b/playground/typescript-jsx-pinia/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-pinia/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-pinia/vite.config.ts b/playground/typescript-jsx-pinia/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-pinia/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-playwright/.gitignore b/playground/typescript-jsx-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/typescript-jsx-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/typescript-jsx-playwright/.vscode/extensions.json b/playground/typescript-jsx-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/typescript-jsx-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/typescript-jsx-playwright/README.md b/playground/typescript-jsx-playwright/README.md new file mode 100644 index 000000000..70d13e4f0 --- /dev/null +++ b/playground/typescript-jsx-playwright/README.md @@ -0,0 +1,59 @@ +# typescript-jsx-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/typescript-jsx-playwright/e2e/tsconfig.json b/playground/typescript-jsx-playwright/e2e/tsconfig.json new file mode 100644 index 000000000..be3bbfc0e --- /dev/null +++ b/playground/typescript-jsx-playwright/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": ["./**/*"] +} diff --git a/playground/typescript-jsx-playwright/e2e/vue.spec.ts b/playground/typescript-jsx-playwright/e2e/vue.spec.ts new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/typescript-jsx-playwright/e2e/vue.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/typescript-jsx-playwright/env.d.ts b/playground/typescript-jsx-playwright/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-playwright/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-playwright/index.html b/playground/typescript-jsx-playwright/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-playwright/package.json b/playground/typescript-jsx-playwright/package.json new file mode 100644 index 000000000..717bf4974 --- /dev/null +++ b/playground/typescript-jsx-playwright/package.json @@ -0,0 +1,29 @@ +{ + "name": "typescript-jsx-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "playwright test", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-playwright/playwright.config.ts b/playground/typescript-jsx-playwright/playwright.config.ts new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/typescript-jsx-playwright/playwright.config.ts @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/typescript-jsx-playwright/public/favicon.ico b/playground/typescript-jsx-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-playwright/src/App.vue b/playground/typescript-jsx-playwright/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx-playwright/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx-playwright/src/assets/logo.svg b/playground/typescript-jsx-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-playwright/src/assets/main.css b/playground/typescript-jsx-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-playwright/src/main.ts b/playground/typescript-jsx-playwright/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript-jsx-playwright/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript-jsx-playwright/tsconfig.app.json b/playground/typescript-jsx-playwright/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-playwright/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-playwright/tsconfig.json b/playground/typescript-jsx-playwright/tsconfig.json new file mode 100644 index 000000000..66b5e5703 --- /dev/null +++ b/playground/typescript-jsx-playwright/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/playground/typescript-jsx-playwright/tsconfig.node.json b/playground/typescript-jsx-playwright/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-playwright/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-playwright/vite.config.ts b/playground/typescript-jsx-playwright/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-playwright/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-cypress/.gitignore b/playground/typescript-jsx-router-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-router-cypress/README.md b/playground/typescript-jsx-router-cypress/README.md new file mode 100644 index 000000000..17bbbfb7f --- /dev/null +++ b/playground/typescript-jsx-router-cypress/README.md @@ -0,0 +1,62 @@ +# typescript-jsx-router-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Headed Component Tests with [Cypress Component Testing](https://on.cypress.io/component) + +```sh +pnpm test:unit:dev # or `pnpm test:unit` for headless testing +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-jsx-router-cypress/cypress.config.ts b/playground/typescript-jsx-router-cypress/cypress.config.ts new file mode 100644 index 000000000..c8fac1298 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/cypress.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + }, + component: { + specPattern: 'src/**/__tests__/*.{cy,spec}.{js,ts,jsx,tsx}', + devServer: { + framework: 'vue', + bundler: 'vite' + } + } +}) diff --git a/playground/typescript-jsx-router-cypress/cypress/e2e/example.cy.ts b/playground/typescript-jsx-router-cypress/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-jsx-router-cypress/cypress/e2e/tsconfig.json b/playground/typescript-jsx-router-cypress/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-jsx-router-cypress/cypress/fixtures/example.json b/playground/typescript-jsx-router-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-jsx-router-cypress/cypress/support/commands.ts b/playground/typescript-jsx-router-cypress/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-jsx-router-cypress/cypress/support/component-index.html b/playground/typescript-jsx-router-cypress/cypress/support/component-index.html new file mode 100644 index 000000000..5f9622ae2 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + Components App + + +
+ + diff --git a/playground/typescript-jsx-router-cypress/cypress/support/component.ts b/playground/typescript-jsx-router-cypress/cypress/support/component.ts new file mode 100644 index 000000000..04e4c352b --- /dev/null +++ b/playground/typescript-jsx-router-cypress/cypress/support/component.ts @@ -0,0 +1,43 @@ +// *********************************************************** +// This example support/component.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') + +// Import global styles +import '@/assets/main.css' + +import { mount } from 'cypress/vue' + +// Augment the Cypress namespace to include type definitions for +// your custom command. +// Alternatively, can be defined in cypress/support/component.d.ts +// with a at the top of your spec. +/* eslint-disable @typescript-eslint/no-namespace */ +declare global { + namespace Cypress { + interface Chainable { + mount: typeof mount + } + } +} + +Cypress.Commands.add('mount', mount) + +// Example use: +// cy.mount(MyComponent) diff --git a/playground/typescript-jsx-router-cypress/cypress/support/e2e.ts b/playground/typescript-jsx-router-cypress/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-jsx-router-cypress/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-jsx-router-cypress/env.d.ts b/playground/typescript-jsx-router-cypress/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router-cypress/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router-cypress/index.html b/playground/typescript-jsx-router-cypress/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router-cypress/package.json b/playground/typescript-jsx-router-cypress/package.json new file mode 100644 index 000000000..03e6238e8 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/package.json @@ -0,0 +1,34 @@ +{ + "name": "typescript-jsx-router-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "test:unit": "cypress run --component", + "test:unit:dev": "cypress open --component", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router-cypress/public/favicon.ico b/playground/typescript-jsx-router-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router-cypress/src/App.vue b/playground/typescript-jsx-router-cypress/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router-cypress/src/assets/logo.svg b/playground/typescript-jsx-router-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router-cypress/src/assets/main.css b/playground/typescript-jsx-router-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router-cypress/src/components/HelloWorld.vue b/playground/typescript-jsx-router-cypress/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router-cypress/src/components/TheWelcome.vue b/playground/typescript-jsx-router-cypress/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router-cypress/src/components/WelcomeItem.vue b/playground/typescript-jsx-router-cypress/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router-cypress/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router-cypress/src/components/__tests__/HelloWorld.cy.ts b/playground/typescript-jsx-router-cypress/src/components/__tests__/HelloWorld.cy.ts new file mode 100644 index 000000000..535a0e51c --- /dev/null +++ b/playground/typescript-jsx-router-cypress/src/components/__tests__/HelloWorld.cy.ts @@ -0,0 +1,12 @@ +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('playground', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + }) + + it('renders properly', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + cy.get('h1').should('contain', 'Hello Cypress') + }) +}) diff --git a/playground/typescript-jsx-router-cypress/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router-cypress/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-cypress/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router-cypress/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router-cypress/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-cypress/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router-cypress/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router-cypress/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-cypress/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router-cypress/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-cypress/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router-cypress/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router-cypress/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router-cypress/src/main.ts b/playground/typescript-jsx-router-cypress/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router-cypress/src/router/index.ts b/playground/typescript-jsx-router-cypress/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router-cypress/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router-cypress/src/views/AboutView.vue b/playground/typescript-jsx-router-cypress/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router-cypress/src/views/HomeView.vue b/playground/typescript-jsx-router-cypress/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router-cypress/tsconfig.app.json b/playground/typescript-jsx-router-cypress/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router-cypress/tsconfig.cypress-ct.json b/playground/typescript-jsx-router-cypress/tsconfig.cypress-ct.json new file mode 100644 index 000000000..12833b275 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/tsconfig.cypress-ct.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.app.json", + "include": [ + "env.d.ts", + "src/**/*", + "src/**/*.vue", + "cypress/support/component.*", + "cypress/support/commands.ts" + ], + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.cypress-ct.tsbuildinfo" + } +} diff --git a/playground/typescript-jsx-router-cypress/tsconfig.json b/playground/typescript-jsx-router-cypress/tsconfig.json new file mode 100644 index 000000000..d3b6c3172 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.cypress-ct.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-jsx-router-cypress/tsconfig.node.json b/playground/typescript-jsx-router-cypress/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router-cypress/vite.config.ts b/playground/typescript-jsx-router-cypress/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-router-cypress/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-nightwatch/.gitignore b/playground/typescript-jsx-router-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/typescript-jsx-router-nightwatch/.vscode/extensions.json b/playground/typescript-jsx-router-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/typescript-jsx-router-nightwatch/README.md b/playground/typescript-jsx-router-nightwatch/README.md new file mode 100644 index 000000000..65ea33378 --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/README.md @@ -0,0 +1,63 @@ +# typescript-jsx-router-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/typescript-jsx-router-nightwatch/env.d.ts b/playground/typescript-jsx-router-nightwatch/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router-nightwatch/index.html b/playground/typescript-jsx-router-nightwatch/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router-nightwatch/nightwatch.conf.cjs b/playground/typescript-jsx-router-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/typescript-jsx-router-nightwatch/nightwatch/index.html b/playground/typescript-jsx-router-nightwatch/nightwatch/index.html new file mode 100644 index 000000000..b7e1ec765 --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/nightwatch/index.html @@ -0,0 +1,16 @@ + + + + + + + + + Vue Renderer + + + +
+ + + diff --git a/playground/typescript-jsx-router-nightwatch/nightwatch/nightwatch.d.ts b/playground/typescript-jsx-router-nightwatch/nightwatch/nightwatch.d.ts new file mode 100644 index 000000000..616e63f9f --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/nightwatch/nightwatch.d.ts @@ -0,0 +1,13 @@ +import { NightwatchCustomAssertions, NightwatchCustomCommands } from 'nightwatch' + +declare module 'nightwatch' { + interface NightwatchCustomAssertions { + // Add your custom assertions' types here + // elementHasCount: (selector: string, count: number) => NightwatchBrowser + } + + interface NightwatchCustomCommands { + // Add your custom commands' types here + // strictClick: (selector: string) => NightwatchBrowser + } +} diff --git a/playground/typescript-jsx-router-nightwatch/nightwatch/tsconfig.json b/playground/typescript-jsx-router-nightwatch/nightwatch/tsconfig.json new file mode 100644 index 000000000..8cd7ca1da --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/nightwatch/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "../node_modules/.tmp/tsconfig.nightwatch.tsbuildinfo", + + "target": "ESNext", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": "../", + "lib": ["ESNext", "dom"], + "types": ["nightwatch"] + }, + "include": ["../node_modules/@nightwatch/**/*", "../src/components/**/*", "../tests/e2e/**/*"], + "ts-node": { + "transpileOnly": true + }, + "files": ["nightwatch.d.ts"] +} diff --git a/playground/typescript-jsx-router-nightwatch/package.json b/playground/typescript-jsx-router-nightwatch/package.json new file mode 100644 index 000000000..38b0f44be --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/package.json @@ -0,0 +1,37 @@ +{ + "name": "typescript-jsx-router-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "nightwatch tests/e2e/*", + "test:unit": "nightwatch src/**/__tests__/*", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "nightwatch": "^3.4.0", + "npm-run-all2": "^6.1.2", + "ts-node": "^10.9.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router-nightwatch/public/favicon.ico b/playground/typescript-jsx-router-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router-nightwatch/src/App.vue b/playground/typescript-jsx-router-nightwatch/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router-nightwatch/src/assets/logo.svg b/playground/typescript-jsx-router-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router-nightwatch/src/assets/main.css b/playground/typescript-jsx-router-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router-nightwatch/src/components/HelloWorld.vue b/playground/typescript-jsx-router-nightwatch/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router-nightwatch/src/components/TheWelcome.vue b/playground/typescript-jsx-router-nightwatch/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router-nightwatch/src/components/WelcomeItem.vue b/playground/typescript-jsx-router-nightwatch/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router-nightwatch/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-router-nightwatch/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..810641e6e --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,14 @@ +describe('Hello World', function () { + before((browser) => { + browser.init() + }) + + it('renders properly', async function () { + const welcomeComponent = await browser.mountComponent('/src/components/HelloWorld.vue', {props: {msg: 'Hello Nightwatch'}}); + + browser.expect.element(welcomeComponent).to.be.present; + browser.expect.element('h1').text.to.contain('Hello Nightwatch'); + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-jsx-router-nightwatch/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router-nightwatch/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-nightwatch/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router-nightwatch/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-nightwatch/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router-nightwatch/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-nightwatch/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router-nightwatch/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-nightwatch/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router-nightwatch/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router-nightwatch/src/main.ts b/playground/typescript-jsx-router-nightwatch/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router-nightwatch/src/router/index.ts b/playground/typescript-jsx-router-nightwatch/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router-nightwatch/src/views/AboutView.vue b/playground/typescript-jsx-router-nightwatch/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router-nightwatch/src/views/HomeView.vue b/playground/typescript-jsx-router-nightwatch/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router-nightwatch/tests/e2e/example.ts b/playground/typescript-jsx-router-nightwatch/tests/e2e/example.ts new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/tests/e2e/example.ts @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-jsx-router-nightwatch/tsconfig.app.json b/playground/typescript-jsx-router-nightwatch/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router-nightwatch/tsconfig.json b/playground/typescript-jsx-router-nightwatch/tsconfig.json new file mode 100644 index 000000000..5c385ae2c --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./nightwatch/tsconfig.json" + } + ] +} diff --git a/playground/typescript-jsx-router-nightwatch/tsconfig.node.json b/playground/typescript-jsx-router-nightwatch/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router-nightwatch/vite.config.ts b/playground/typescript-jsx-router-nightwatch/vite.config.ts new file mode 100644 index 000000000..3e49bf0ca --- /dev/null +++ b/playground/typescript-jsx-router-nightwatch/vite.config.ts @@ -0,0 +1,22 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + nightwatchPlugin({ + renderPage: './nightwatch/index.html' + }), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-pinia-cypress/.gitignore b/playground/typescript-jsx-router-pinia-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-router-pinia-cypress/README.md b/playground/typescript-jsx-router-pinia-cypress/README.md new file mode 100644 index 000000000..1b67b664d --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/README.md @@ -0,0 +1,62 @@ +# typescript-jsx-router-pinia-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Headed Component Tests with [Cypress Component Testing](https://on.cypress.io/component) + +```sh +pnpm test:unit:dev # or `pnpm test:unit` for headless testing +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-jsx-router-pinia-cypress/cypress.config.ts b/playground/typescript-jsx-router-pinia-cypress/cypress.config.ts new file mode 100644 index 000000000..c8fac1298 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/cypress.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + }, + component: { + specPattern: 'src/**/__tests__/*.{cy,spec}.{js,ts,jsx,tsx}', + devServer: { + framework: 'vue', + bundler: 'vite' + } + } +}) diff --git a/playground/typescript-jsx-router-pinia-cypress/cypress/e2e/example.cy.ts b/playground/typescript-jsx-router-pinia-cypress/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-jsx-router-pinia-cypress/cypress/e2e/tsconfig.json b/playground/typescript-jsx-router-pinia-cypress/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-jsx-router-pinia-cypress/cypress/fixtures/example.json b/playground/typescript-jsx-router-pinia-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-jsx-router-pinia-cypress/cypress/support/commands.ts b/playground/typescript-jsx-router-pinia-cypress/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-jsx-router-pinia-cypress/cypress/support/component-index.html b/playground/typescript-jsx-router-pinia-cypress/cypress/support/component-index.html new file mode 100644 index 000000000..5f9622ae2 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + Components App + + +
+ + diff --git a/playground/typescript-jsx-router-pinia-cypress/cypress/support/component.ts b/playground/typescript-jsx-router-pinia-cypress/cypress/support/component.ts new file mode 100644 index 000000000..04e4c352b --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/cypress/support/component.ts @@ -0,0 +1,43 @@ +// *********************************************************** +// This example support/component.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') + +// Import global styles +import '@/assets/main.css' + +import { mount } from 'cypress/vue' + +// Augment the Cypress namespace to include type definitions for +// your custom command. +// Alternatively, can be defined in cypress/support/component.d.ts +// with a at the top of your spec. +/* eslint-disable @typescript-eslint/no-namespace */ +declare global { + namespace Cypress { + interface Chainable { + mount: typeof mount + } + } +} + +Cypress.Commands.add('mount', mount) + +// Example use: +// cy.mount(MyComponent) diff --git a/playground/typescript-jsx-router-pinia-cypress/cypress/support/e2e.ts b/playground/typescript-jsx-router-pinia-cypress/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-jsx-router-pinia-cypress/env.d.ts b/playground/typescript-jsx-router-pinia-cypress/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router-pinia-cypress/index.html b/playground/typescript-jsx-router-pinia-cypress/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router-pinia-cypress/package.json b/playground/typescript-jsx-router-pinia-cypress/package.json new file mode 100644 index 000000000..52818721f --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/package.json @@ -0,0 +1,35 @@ +{ + "name": "typescript-jsx-router-pinia-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "test:unit": "cypress run --component", + "test:unit:dev": "cypress open --component", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router-pinia-cypress/public/favicon.ico b/playground/typescript-jsx-router-pinia-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router-pinia-cypress/src/App.vue b/playground/typescript-jsx-router-pinia-cypress/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia-cypress/src/assets/logo.svg b/playground/typescript-jsx-router-pinia-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router-pinia-cypress/src/assets/main.css b/playground/typescript-jsx-router-pinia-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router-pinia-cypress/src/components/HelloWorld.vue b/playground/typescript-jsx-router-pinia-cypress/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia-cypress/src/components/TheWelcome.vue b/playground/typescript-jsx-router-pinia-cypress/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-cypress/src/components/WelcomeItem.vue b/playground/typescript-jsx-router-pinia-cypress/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-cypress/src/components/__tests__/HelloWorld.cy.ts b/playground/typescript-jsx-router-pinia-cypress/src/components/__tests__/HelloWorld.cy.ts new file mode 100644 index 000000000..535a0e51c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/src/components/__tests__/HelloWorld.cy.ts @@ -0,0 +1,12 @@ +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('playground', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + }) + + it('renders properly', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + cy.get('h1').should('contain', 'Hello Cypress') + }) +}) diff --git a/playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router-pinia-cypress/src/main.ts b/playground/typescript-jsx-router-pinia-cypress/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router-pinia-cypress/src/router/index.ts b/playground/typescript-jsx-router-pinia-cypress/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router-pinia-cypress/src/stores/counter.ts b/playground/typescript-jsx-router-pinia-cypress/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-router-pinia-cypress/src/views/AboutView.vue b/playground/typescript-jsx-router-pinia-cypress/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-cypress/src/views/HomeView.vue b/playground/typescript-jsx-router-pinia-cypress/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-cypress/tsconfig.app.json b/playground/typescript-jsx-router-pinia-cypress/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router-pinia-cypress/tsconfig.cypress-ct.json b/playground/typescript-jsx-router-pinia-cypress/tsconfig.cypress-ct.json new file mode 100644 index 000000000..12833b275 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/tsconfig.cypress-ct.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.app.json", + "include": [ + "env.d.ts", + "src/**/*", + "src/**/*.vue", + "cypress/support/component.*", + "cypress/support/commands.ts" + ], + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.cypress-ct.tsbuildinfo" + } +} diff --git a/playground/typescript-jsx-router-pinia-cypress/tsconfig.json b/playground/typescript-jsx-router-pinia-cypress/tsconfig.json new file mode 100644 index 000000000..d3b6c3172 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.cypress-ct.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-jsx-router-pinia-cypress/tsconfig.node.json b/playground/typescript-jsx-router-pinia-cypress/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router-pinia-cypress/vite.config.ts b/playground/typescript-jsx-router-pinia-cypress/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-cypress/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-pinia-nightwatch/.gitignore b/playground/typescript-jsx-router-pinia-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/typescript-jsx-router-pinia-nightwatch/.vscode/extensions.json b/playground/typescript-jsx-router-pinia-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/typescript-jsx-router-pinia-nightwatch/README.md b/playground/typescript-jsx-router-pinia-nightwatch/README.md new file mode 100644 index 000000000..30ddad29b --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/README.md @@ -0,0 +1,63 @@ +# typescript-jsx-router-pinia-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/typescript-jsx-router-pinia-nightwatch/env.d.ts b/playground/typescript-jsx-router-pinia-nightwatch/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router-pinia-nightwatch/index.html b/playground/typescript-jsx-router-pinia-nightwatch/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router-pinia-nightwatch/nightwatch.conf.cjs b/playground/typescript-jsx-router-pinia-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/typescript-jsx-router-pinia-nightwatch/nightwatch/index.html b/playground/typescript-jsx-router-pinia-nightwatch/nightwatch/index.html new file mode 100644 index 000000000..b7e1ec765 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/nightwatch/index.html @@ -0,0 +1,16 @@ + + + + + + + + + Vue Renderer + + + +
+ + + diff --git a/playground/typescript-jsx-router-pinia-nightwatch/nightwatch/nightwatch.d.ts b/playground/typescript-jsx-router-pinia-nightwatch/nightwatch/nightwatch.d.ts new file mode 100644 index 000000000..616e63f9f --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/nightwatch/nightwatch.d.ts @@ -0,0 +1,13 @@ +import { NightwatchCustomAssertions, NightwatchCustomCommands } from 'nightwatch' + +declare module 'nightwatch' { + interface NightwatchCustomAssertions { + // Add your custom assertions' types here + // elementHasCount: (selector: string, count: number) => NightwatchBrowser + } + + interface NightwatchCustomCommands { + // Add your custom commands' types here + // strictClick: (selector: string) => NightwatchBrowser + } +} diff --git a/playground/typescript-jsx-router-pinia-nightwatch/nightwatch/tsconfig.json b/playground/typescript-jsx-router-pinia-nightwatch/nightwatch/tsconfig.json new file mode 100644 index 000000000..8cd7ca1da --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/nightwatch/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "../node_modules/.tmp/tsconfig.nightwatch.tsbuildinfo", + + "target": "ESNext", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": "../", + "lib": ["ESNext", "dom"], + "types": ["nightwatch"] + }, + "include": ["../node_modules/@nightwatch/**/*", "../src/components/**/*", "../tests/e2e/**/*"], + "ts-node": { + "transpileOnly": true + }, + "files": ["nightwatch.d.ts"] +} diff --git a/playground/typescript-jsx-router-pinia-nightwatch/package.json b/playground/typescript-jsx-router-pinia-nightwatch/package.json new file mode 100644 index 000000000..ce53cbd57 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/package.json @@ -0,0 +1,38 @@ +{ + "name": "typescript-jsx-router-pinia-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "nightwatch tests/e2e/*", + "test:unit": "nightwatch src/**/__tests__/*", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "nightwatch": "^3.4.0", + "npm-run-all2": "^6.1.2", + "ts-node": "^10.9.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router-pinia-nightwatch/public/favicon.ico b/playground/typescript-jsx-router-pinia-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router-pinia-nightwatch/src/App.vue b/playground/typescript-jsx-router-pinia-nightwatch/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia-nightwatch/src/assets/logo.svg b/playground/typescript-jsx-router-pinia-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router-pinia-nightwatch/src/assets/main.css b/playground/typescript-jsx-router-pinia-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router-pinia-nightwatch/src/components/HelloWorld.vue b/playground/typescript-jsx-router-pinia-nightwatch/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia-nightwatch/src/components/TheWelcome.vue b/playground/typescript-jsx-router-pinia-nightwatch/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-nightwatch/src/components/WelcomeItem.vue b/playground/typescript-jsx-router-pinia-nightwatch/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-router-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..810641e6e --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,14 @@ +describe('Hello World', function () { + before((browser) => { + browser.init() + }) + + it('renders properly', async function () { + const welcomeComponent = await browser.mountComponent('/src/components/HelloWorld.vue', {props: {msg: 'Hello Nightwatch'}}); + + browser.expect.element(welcomeComponent).to.be.present; + browser.expect.element('h1').text.to.contain('Hello Nightwatch'); + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router-pinia-nightwatch/src/main.ts b/playground/typescript-jsx-router-pinia-nightwatch/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router-pinia-nightwatch/src/router/index.ts b/playground/typescript-jsx-router-pinia-nightwatch/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router-pinia-nightwatch/src/stores/counter.ts b/playground/typescript-jsx-router-pinia-nightwatch/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-router-pinia-nightwatch/src/views/AboutView.vue b/playground/typescript-jsx-router-pinia-nightwatch/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-nightwatch/src/views/HomeView.vue b/playground/typescript-jsx-router-pinia-nightwatch/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-nightwatch/tests/e2e/example.ts b/playground/typescript-jsx-router-pinia-nightwatch/tests/e2e/example.ts new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/tests/e2e/example.ts @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-jsx-router-pinia-nightwatch/tsconfig.app.json b/playground/typescript-jsx-router-pinia-nightwatch/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router-pinia-nightwatch/tsconfig.json b/playground/typescript-jsx-router-pinia-nightwatch/tsconfig.json new file mode 100644 index 000000000..5c385ae2c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./nightwatch/tsconfig.json" + } + ] +} diff --git a/playground/typescript-jsx-router-pinia-nightwatch/tsconfig.node.json b/playground/typescript-jsx-router-pinia-nightwatch/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router-pinia-nightwatch/vite.config.ts b/playground/typescript-jsx-router-pinia-nightwatch/vite.config.ts new file mode 100644 index 000000000..3e49bf0ca --- /dev/null +++ b/playground/typescript-jsx-router-pinia-nightwatch/vite.config.ts @@ -0,0 +1,22 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + nightwatchPlugin({ + renderPage: './nightwatch/index.html' + }), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-pinia-playwright/.gitignore b/playground/typescript-jsx-router-pinia-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/typescript-jsx-router-pinia-playwright/.vscode/extensions.json b/playground/typescript-jsx-router-pinia-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/typescript-jsx-router-pinia-playwright/README.md b/playground/typescript-jsx-router-pinia-playwright/README.md new file mode 100644 index 000000000..907b58e9f --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/README.md @@ -0,0 +1,59 @@ +# typescript-jsx-router-pinia-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/typescript-jsx-router-pinia-playwright/e2e/tsconfig.json b/playground/typescript-jsx-router-pinia-playwright/e2e/tsconfig.json new file mode 100644 index 000000000..be3bbfc0e --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": ["./**/*"] +} diff --git a/playground/typescript-jsx-router-pinia-playwright/e2e/vue.spec.ts b/playground/typescript-jsx-router-pinia-playwright/e2e/vue.spec.ts new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/e2e/vue.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/typescript-jsx-router-pinia-playwright/env.d.ts b/playground/typescript-jsx-router-pinia-playwright/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router-pinia-playwright/index.html b/playground/typescript-jsx-router-pinia-playwright/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router-pinia-playwright/package.json b/playground/typescript-jsx-router-pinia-playwright/package.json new file mode 100644 index 000000000..26f93b008 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/package.json @@ -0,0 +1,31 @@ +{ + "name": "typescript-jsx-router-pinia-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "playwright test", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router-pinia-playwright/playwright.config.ts b/playground/typescript-jsx-router-pinia-playwright/playwright.config.ts new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/playwright.config.ts @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/typescript-jsx-router-pinia-playwright/public/favicon.ico b/playground/typescript-jsx-router-pinia-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router-pinia-playwright/src/App.vue b/playground/typescript-jsx-router-pinia-playwright/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia-playwright/src/assets/logo.svg b/playground/typescript-jsx-router-pinia-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router-pinia-playwright/src/assets/main.css b/playground/typescript-jsx-router-pinia-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router-pinia-playwright/src/components/HelloWorld.vue b/playground/typescript-jsx-router-pinia-playwright/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia-playwright/src/components/TheWelcome.vue b/playground/typescript-jsx-router-pinia-playwright/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-playwright/src/components/WelcomeItem.vue b/playground/typescript-jsx-router-pinia-playwright/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router-pinia-playwright/src/main.ts b/playground/typescript-jsx-router-pinia-playwright/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router-pinia-playwright/src/router/index.ts b/playground/typescript-jsx-router-pinia-playwright/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router-pinia-playwright/src/stores/counter.ts b/playground/typescript-jsx-router-pinia-playwright/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-router-pinia-playwright/src/views/AboutView.vue b/playground/typescript-jsx-router-pinia-playwright/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-playwright/src/views/HomeView.vue b/playground/typescript-jsx-router-pinia-playwright/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-playwright/tsconfig.app.json b/playground/typescript-jsx-router-pinia-playwright/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router-pinia-playwright/tsconfig.json b/playground/typescript-jsx-router-pinia-playwright/tsconfig.json new file mode 100644 index 000000000..66b5e5703 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/playground/typescript-jsx-router-pinia-playwright/tsconfig.node.json b/playground/typescript-jsx-router-pinia-playwright/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router-pinia-playwright/vite.config.ts b/playground/typescript-jsx-router-pinia-playwright/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-playwright/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/.gitignore b/playground/typescript-jsx-router-pinia-vitest-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/README.md b/playground/typescript-jsx-router-pinia-vitest-cypress/README.md new file mode 100644 index 000000000..9a2410570 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/README.md @@ -0,0 +1,62 @@ +# typescript-jsx-router-pinia-vitest-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/cypress.config.ts b/playground/typescript-jsx-router-pinia-vitest-cypress/cypress.config.ts new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/cypress.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/cypress/e2e/example.cy.ts b/playground/typescript-jsx-router-pinia-vitest-cypress/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/cypress/e2e/tsconfig.json b/playground/typescript-jsx-router-pinia-vitest-cypress/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/cypress/fixtures/example.json b/playground/typescript-jsx-router-pinia-vitest-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/cypress/support/commands.ts b/playground/typescript-jsx-router-pinia-vitest-cypress/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/cypress/support/e2e.ts b/playground/typescript-jsx-router-pinia-vitest-cypress/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/env.d.ts b/playground/typescript-jsx-router-pinia-vitest-cypress/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/index.html b/playground/typescript-jsx-router-pinia-vitest-cypress/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/package.json b/playground/typescript-jsx-router-pinia-vitest-cypress/package.json new file mode 100644 index 000000000..58d5b141e --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/package.json @@ -0,0 +1,38 @@ +{ + "name": "typescript-jsx-router-pinia-vitest-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/public/favicon.ico b/playground/typescript-jsx-router-pinia-vitest-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/src/App.vue b/playground/typescript-jsx-router-pinia-vitest-cypress/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/src/assets/logo.svg b/playground/typescript-jsx-router-pinia-vitest-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/src/assets/main.css b/playground/typescript-jsx-router-pinia-vitest-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/HelloWorld.vue b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/TheWelcome.vue b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/WelcomeItem.vue b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/src/main.ts b/playground/typescript-jsx-router-pinia-vitest-cypress/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/src/router/index.ts b/playground/typescript-jsx-router-pinia-vitest-cypress/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/src/stores/counter.ts b/playground/typescript-jsx-router-pinia-vitest-cypress/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/src/views/AboutView.vue b/playground/typescript-jsx-router-pinia-vitest-cypress/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/src/views/HomeView.vue b/playground/typescript-jsx-router-pinia-vitest-cypress/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/tsconfig.app.json b/playground/typescript-jsx-router-pinia-vitest-cypress/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/tsconfig.json b/playground/typescript-jsx-router-pinia-vitest-cypress/tsconfig.json new file mode 100644 index 000000000..5304731b8 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/tsconfig.node.json b/playground/typescript-jsx-router-pinia-vitest-cypress/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/tsconfig.vitest.json b/playground/typescript-jsx-router-pinia-vitest-cypress/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/vite.config.ts b/playground/typescript-jsx-router-pinia-vitest-cypress/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-pinia-vitest-cypress/vitest.config.ts b/playground/typescript-jsx-router-pinia-vitest-cypress/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-cypress/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/.gitignore b/playground/typescript-jsx-router-pinia-vitest-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/.vscode/extensions.json b/playground/typescript-jsx-router-pinia-vitest-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/README.md b/playground/typescript-jsx-router-pinia-vitest-nightwatch/README.md new file mode 100644 index 000000000..256859bfe --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/README.md @@ -0,0 +1,69 @@ +# typescript-jsx-router-pinia-vitest-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/env.d.ts b/playground/typescript-jsx-router-pinia-vitest-nightwatch/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/index.html b/playground/typescript-jsx-router-pinia-vitest-nightwatch/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/nightwatch.conf.cjs b/playground/typescript-jsx-router-pinia-vitest-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/nightwatch/nightwatch.d.ts b/playground/typescript-jsx-router-pinia-vitest-nightwatch/nightwatch/nightwatch.d.ts new file mode 100644 index 000000000..616e63f9f --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/nightwatch/nightwatch.d.ts @@ -0,0 +1,13 @@ +import { NightwatchCustomAssertions, NightwatchCustomCommands } from 'nightwatch' + +declare module 'nightwatch' { + interface NightwatchCustomAssertions { + // Add your custom assertions' types here + // elementHasCount: (selector: string, count: number) => NightwatchBrowser + } + + interface NightwatchCustomCommands { + // Add your custom commands' types here + // strictClick: (selector: string) => NightwatchBrowser + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/nightwatch/tsconfig.json b/playground/typescript-jsx-router-pinia-vitest-nightwatch/nightwatch/tsconfig.json new file mode 100644 index 000000000..8cd7ca1da --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/nightwatch/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "../node_modules/.tmp/tsconfig.nightwatch.tsbuildinfo", + + "target": "ESNext", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": "../", + "lib": ["ESNext", "dom"], + "types": ["nightwatch"] + }, + "include": ["../node_modules/@nightwatch/**/*", "../src/components/**/*", "../tests/e2e/**/*"], + "ts-node": { + "transpileOnly": true + }, + "files": ["nightwatch.d.ts"] +} diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/package.json b/playground/typescript-jsx-router-pinia-vitest-nightwatch/package.json new file mode 100644 index 000000000..59f3d45dc --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/package.json @@ -0,0 +1,41 @@ +{ + "name": "typescript-jsx-router-pinia-vitest-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "nightwatch tests/e2e/*", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "jsdom": "^24.0.0", + "nightwatch": "^3.4.0", + "npm-run-all2": "^6.1.2", + "ts-node": "^10.9.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/public/favicon.ico b/playground/typescript-jsx-router-pinia-vitest-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/App.vue b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/assets/logo.svg b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/assets/main.css b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/HelloWorld.vue b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/TheWelcome.vue b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/WelcomeItem.vue b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/main.ts b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/router/index.ts b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/stores/counter.ts b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/views/AboutView.vue b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/views/HomeView.vue b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/tests/e2e/example.ts b/playground/typescript-jsx-router-pinia-vitest-nightwatch/tests/e2e/example.ts new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/tests/e2e/example.ts @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/tsconfig.app.json b/playground/typescript-jsx-router-pinia-vitest-nightwatch/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/tsconfig.json b/playground/typescript-jsx-router-pinia-vitest-nightwatch/tsconfig.json new file mode 100644 index 000000000..a5352e667 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + }, + { + "path": "./nightwatch/tsconfig.json" + } + ] +} diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/tsconfig.node.json b/playground/typescript-jsx-router-pinia-vitest-nightwatch/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/tsconfig.vitest.json b/playground/typescript-jsx-router-pinia-vitest-nightwatch/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/vite.config.ts b/playground/typescript-jsx-router-pinia-vitest-nightwatch/vite.config.ts new file mode 100644 index 000000000..3a6988230 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/vite.config.ts @@ -0,0 +1,20 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + nightwatchPlugin(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-pinia-vitest-nightwatch/vitest.config.ts b/playground/typescript-jsx-router-pinia-vitest-nightwatch/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-nightwatch/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/.gitignore b/playground/typescript-jsx-router-pinia-vitest-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/.vscode/extensions.json b/playground/typescript-jsx-router-pinia-vitest-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/README.md b/playground/typescript-jsx-router-pinia-vitest-playwright/README.md new file mode 100644 index 000000000..e4650e499 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/README.md @@ -0,0 +1,65 @@ +# typescript-jsx-router-pinia-vitest-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/e2e/tsconfig.json b/playground/typescript-jsx-router-pinia-vitest-playwright/e2e/tsconfig.json new file mode 100644 index 000000000..be3bbfc0e --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": ["./**/*"] +} diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/e2e/vue.spec.ts b/playground/typescript-jsx-router-pinia-vitest-playwright/e2e/vue.spec.ts new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/e2e/vue.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/env.d.ts b/playground/typescript-jsx-router-pinia-vitest-playwright/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/index.html b/playground/typescript-jsx-router-pinia-vitest-playwright/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/package.json b/playground/typescript-jsx-router-pinia-vitest-playwright/package.json new file mode 100644 index 000000000..d3e765479 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/package.json @@ -0,0 +1,36 @@ +{ + "name": "typescript-jsx-router-pinia-vitest-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "playwright test", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/playwright.config.ts b/playground/typescript-jsx-router-pinia-vitest-playwright/playwright.config.ts new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/playwright.config.ts @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/public/favicon.ico b/playground/typescript-jsx-router-pinia-vitest-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/src/App.vue b/playground/typescript-jsx-router-pinia-vitest-playwright/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/src/assets/logo.svg b/playground/typescript-jsx-router-pinia-vitest-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/src/assets/main.css b/playground/typescript-jsx-router-pinia-vitest-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/HelloWorld.vue b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/TheWelcome.vue b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/WelcomeItem.vue b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/src/main.ts b/playground/typescript-jsx-router-pinia-vitest-playwright/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/src/router/index.ts b/playground/typescript-jsx-router-pinia-vitest-playwright/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/src/stores/counter.ts b/playground/typescript-jsx-router-pinia-vitest-playwright/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/src/views/AboutView.vue b/playground/typescript-jsx-router-pinia-vitest-playwright/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/src/views/HomeView.vue b/playground/typescript-jsx-router-pinia-vitest-playwright/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/tsconfig.app.json b/playground/typescript-jsx-router-pinia-vitest-playwright/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/tsconfig.json b/playground/typescript-jsx-router-pinia-vitest-playwright/tsconfig.json new file mode 100644 index 000000000..100cf6a8f --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ] +} diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/tsconfig.node.json b/playground/typescript-jsx-router-pinia-vitest-playwright/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/tsconfig.vitest.json b/playground/typescript-jsx-router-pinia-vitest-playwright/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/vite.config.ts b/playground/typescript-jsx-router-pinia-vitest-playwright/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-pinia-vitest-playwright/vitest.config.ts b/playground/typescript-jsx-router-pinia-vitest-playwright/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest-playwright/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-router-pinia-vitest/.gitignore b/playground/typescript-jsx-router-pinia-vitest/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-router-pinia-vitest/README.md b/playground/typescript-jsx-router-pinia-vitest/README.md new file mode 100644 index 000000000..6561c3315 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/README.md @@ -0,0 +1,46 @@ +# typescript-jsx-router-pinia-vitest + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` diff --git a/playground/typescript-jsx-router-pinia-vitest/env.d.ts b/playground/typescript-jsx-router-pinia-vitest/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router-pinia-vitest/index.html b/playground/typescript-jsx-router-pinia-vitest/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router-pinia-vitest/package.json b/playground/typescript-jsx-router-pinia-vitest/package.json new file mode 100644 index 000000000..a361e6c2a --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/package.json @@ -0,0 +1,34 @@ +{ + "name": "typescript-jsx-router-pinia-vitest", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest/public/favicon.ico b/playground/typescript-jsx-router-pinia-vitest/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router-pinia-vitest/src/App.vue b/playground/typescript-jsx-router-pinia-vitest/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia-vitest/src/assets/logo.svg b/playground/typescript-jsx-router-pinia-vitest/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest/src/assets/main.css b/playground/typescript-jsx-router-pinia-vitest/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router-pinia-vitest/src/components/HelloWorld.vue b/playground/typescript-jsx-router-pinia-vitest/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia-vitest/src/components/TheWelcome.vue b/playground/typescript-jsx-router-pinia-vitest/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-vitest/src/components/WelcomeItem.vue b/playground/typescript-jsx-router-pinia-vitest/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-vitest/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-router-pinia-vitest/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router-pinia-vitest/src/main.ts b/playground/typescript-jsx-router-pinia-vitest/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router-pinia-vitest/src/router/index.ts b/playground/typescript-jsx-router-pinia-vitest/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router-pinia-vitest/src/stores/counter.ts b/playground/typescript-jsx-router-pinia-vitest/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-router-pinia-vitest/src/views/AboutView.vue b/playground/typescript-jsx-router-pinia-vitest/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-vitest/src/views/HomeView.vue b/playground/typescript-jsx-router-pinia-vitest/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-vitest/tsconfig.app.json b/playground/typescript-jsx-router-pinia-vitest/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest/tsconfig.json b/playground/typescript-jsx-router-pinia-vitest/tsconfig.json new file mode 100644 index 000000000..100cf6a8f --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ] +} diff --git a/playground/typescript-jsx-router-pinia-vitest/tsconfig.node.json b/playground/typescript-jsx-router-pinia-vitest/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest/tsconfig.vitest.json b/playground/typescript-jsx-router-pinia-vitest/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-router-pinia-vitest/vite.config.ts b/playground/typescript-jsx-router-pinia-vitest/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-pinia-vitest/vitest.config.ts b/playground/typescript-jsx-router-pinia-vitest/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-vitest/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-router-pinia-with-tests/.gitignore b/playground/typescript-jsx-router-pinia-with-tests/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-router-pinia-with-tests/README.md b/playground/typescript-jsx-router-pinia-with-tests/README.md new file mode 100644 index 000000000..cfbfc7f7e --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/README.md @@ -0,0 +1,62 @@ +# typescript-jsx-router-pinia-with-tests + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-jsx-router-pinia-with-tests/cypress.config.ts b/playground/typescript-jsx-router-pinia-with-tests/cypress.config.ts new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/cypress.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/typescript-jsx-router-pinia-with-tests/cypress/e2e/example.cy.ts b/playground/typescript-jsx-router-pinia-with-tests/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-jsx-router-pinia-with-tests/cypress/e2e/tsconfig.json b/playground/typescript-jsx-router-pinia-with-tests/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-jsx-router-pinia-with-tests/cypress/fixtures/example.json b/playground/typescript-jsx-router-pinia-with-tests/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-jsx-router-pinia-with-tests/cypress/support/commands.ts b/playground/typescript-jsx-router-pinia-with-tests/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-jsx-router-pinia-with-tests/cypress/support/e2e.ts b/playground/typescript-jsx-router-pinia-with-tests/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-jsx-router-pinia-with-tests/env.d.ts b/playground/typescript-jsx-router-pinia-with-tests/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router-pinia-with-tests/index.html b/playground/typescript-jsx-router-pinia-with-tests/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router-pinia-with-tests/package.json b/playground/typescript-jsx-router-pinia-with-tests/package.json new file mode 100644 index 000000000..8f521220b --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/package.json @@ -0,0 +1,38 @@ +{ + "name": "typescript-jsx-router-pinia-with-tests", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router-pinia-with-tests/public/favicon.ico b/playground/typescript-jsx-router-pinia-with-tests/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router-pinia-with-tests/src/App.vue b/playground/typescript-jsx-router-pinia-with-tests/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia-with-tests/src/assets/logo.svg b/playground/typescript-jsx-router-pinia-with-tests/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router-pinia-with-tests/src/assets/main.css b/playground/typescript-jsx-router-pinia-with-tests/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router-pinia-with-tests/src/components/HelloWorld.vue b/playground/typescript-jsx-router-pinia-with-tests/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia-with-tests/src/components/TheWelcome.vue b/playground/typescript-jsx-router-pinia-with-tests/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-with-tests/src/components/WelcomeItem.vue b/playground/typescript-jsx-router-pinia-with-tests/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-with-tests/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-router-pinia-with-tests/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router-pinia-with-tests/src/main.ts b/playground/typescript-jsx-router-pinia-with-tests/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router-pinia-with-tests/src/router/index.ts b/playground/typescript-jsx-router-pinia-with-tests/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router-pinia-with-tests/src/stores/counter.ts b/playground/typescript-jsx-router-pinia-with-tests/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-router-pinia-with-tests/src/views/AboutView.vue b/playground/typescript-jsx-router-pinia-with-tests/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-with-tests/src/views/HomeView.vue b/playground/typescript-jsx-router-pinia-with-tests/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router-pinia-with-tests/tsconfig.app.json b/playground/typescript-jsx-router-pinia-with-tests/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router-pinia-with-tests/tsconfig.json b/playground/typescript-jsx-router-pinia-with-tests/tsconfig.json new file mode 100644 index 000000000..5304731b8 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-jsx-router-pinia-with-tests/tsconfig.node.json b/playground/typescript-jsx-router-pinia-with-tests/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router-pinia-with-tests/tsconfig.vitest.json b/playground/typescript-jsx-router-pinia-with-tests/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-router-pinia-with-tests/vite.config.ts b/playground/typescript-jsx-router-pinia-with-tests/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-pinia-with-tests/vitest.config.ts b/playground/typescript-jsx-router-pinia-with-tests/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-router-pinia-with-tests/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-router-pinia/.gitignore b/playground/typescript-jsx-router-pinia/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-router-pinia/README.md b/playground/typescript-jsx-router-pinia/README.md new file mode 100644 index 000000000..dc923bd03 --- /dev/null +++ b/playground/typescript-jsx-router-pinia/README.md @@ -0,0 +1,40 @@ +# typescript-jsx-router-pinia + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` diff --git a/playground/typescript-jsx-router-pinia/env.d.ts b/playground/typescript-jsx-router-pinia/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router-pinia/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router-pinia/index.html b/playground/typescript-jsx-router-pinia/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router-pinia/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router-pinia/package.json b/playground/typescript-jsx-router-pinia/package.json new file mode 100644 index 000000000..65a59563f --- /dev/null +++ b/playground/typescript-jsx-router-pinia/package.json @@ -0,0 +1,29 @@ +{ + "name": "typescript-jsx-router-pinia", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router-pinia/public/favicon.ico b/playground/typescript-jsx-router-pinia/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router-pinia/src/App.vue b/playground/typescript-jsx-router-pinia/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router-pinia/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia/src/assets/logo.svg b/playground/typescript-jsx-router-pinia/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router-pinia/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router-pinia/src/assets/main.css b/playground/typescript-jsx-router-pinia/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router-pinia/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router-pinia/src/components/HelloWorld.vue b/playground/typescript-jsx-router-pinia/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router-pinia/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router-pinia/src/components/TheWelcome.vue b/playground/typescript-jsx-router-pinia/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router-pinia/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router-pinia/src/components/WelcomeItem.vue b/playground/typescript-jsx-router-pinia/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router-pinia/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router-pinia/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router-pinia/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router-pinia/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router-pinia/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router-pinia/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router-pinia/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router-pinia/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router-pinia/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-pinia/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router-pinia/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router-pinia/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router-pinia/src/main.ts b/playground/typescript-jsx-router-pinia/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router-pinia/src/router/index.ts b/playground/typescript-jsx-router-pinia/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router-pinia/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router-pinia/src/stores/counter.ts b/playground/typescript-jsx-router-pinia/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-jsx-router-pinia/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-jsx-router-pinia/src/views/AboutView.vue b/playground/typescript-jsx-router-pinia/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router-pinia/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router-pinia/src/views/HomeView.vue b/playground/typescript-jsx-router-pinia/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router-pinia/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router-pinia/tsconfig.app.json b/playground/typescript-jsx-router-pinia/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router-pinia/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router-pinia/tsconfig.json b/playground/typescript-jsx-router-pinia/tsconfig.json new file mode 100644 index 000000000..66b5e5703 --- /dev/null +++ b/playground/typescript-jsx-router-pinia/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/playground/typescript-jsx-router-pinia/tsconfig.node.json b/playground/typescript-jsx-router-pinia/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router-pinia/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router-pinia/vite.config.ts b/playground/typescript-jsx-router-pinia/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-router-pinia/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-playwright/.gitignore b/playground/typescript-jsx-router-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/typescript-jsx-router-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/typescript-jsx-router-playwright/.vscode/extensions.json b/playground/typescript-jsx-router-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/typescript-jsx-router-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/typescript-jsx-router-playwright/README.md b/playground/typescript-jsx-router-playwright/README.md new file mode 100644 index 000000000..eaca2b354 --- /dev/null +++ b/playground/typescript-jsx-router-playwright/README.md @@ -0,0 +1,59 @@ +# typescript-jsx-router-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/typescript-jsx-router-playwright/e2e/tsconfig.json b/playground/typescript-jsx-router-playwright/e2e/tsconfig.json new file mode 100644 index 000000000..be3bbfc0e --- /dev/null +++ b/playground/typescript-jsx-router-playwright/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": ["./**/*"] +} diff --git a/playground/typescript-jsx-router-playwright/e2e/vue.spec.ts b/playground/typescript-jsx-router-playwright/e2e/vue.spec.ts new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/typescript-jsx-router-playwright/e2e/vue.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/typescript-jsx-router-playwright/env.d.ts b/playground/typescript-jsx-router-playwright/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router-playwright/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router-playwright/index.html b/playground/typescript-jsx-router-playwright/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router-playwright/package.json b/playground/typescript-jsx-router-playwright/package.json new file mode 100644 index 000000000..a1afa5663 --- /dev/null +++ b/playground/typescript-jsx-router-playwright/package.json @@ -0,0 +1,30 @@ +{ + "name": "typescript-jsx-router-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "playwright test", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router-playwright/playwright.config.ts b/playground/typescript-jsx-router-playwright/playwright.config.ts new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/typescript-jsx-router-playwright/playwright.config.ts @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/typescript-jsx-router-playwright/public/favicon.ico b/playground/typescript-jsx-router-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router-playwright/src/App.vue b/playground/typescript-jsx-router-playwright/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router-playwright/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router-playwright/src/assets/logo.svg b/playground/typescript-jsx-router-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router-playwright/src/assets/main.css b/playground/typescript-jsx-router-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router-playwright/src/components/HelloWorld.vue b/playground/typescript-jsx-router-playwright/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router-playwright/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router-playwright/src/components/TheWelcome.vue b/playground/typescript-jsx-router-playwright/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router-playwright/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router-playwright/src/components/WelcomeItem.vue b/playground/typescript-jsx-router-playwright/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router-playwright/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router-playwright/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router-playwright/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router-playwright/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-playwright/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router-playwright/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router-playwright/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-playwright/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router-playwright/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router-playwright/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-playwright/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router-playwright/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router-playwright/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-playwright/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router-playwright/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router-playwright/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router-playwright/src/main.ts b/playground/typescript-jsx-router-playwright/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-jsx-router-playwright/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router-playwright/src/router/index.ts b/playground/typescript-jsx-router-playwright/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router-playwright/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router-playwright/src/views/AboutView.vue b/playground/typescript-jsx-router-playwright/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router-playwright/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router-playwright/src/views/HomeView.vue b/playground/typescript-jsx-router-playwright/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router-playwright/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router-playwright/tsconfig.app.json b/playground/typescript-jsx-router-playwright/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router-playwright/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router-playwright/tsconfig.json b/playground/typescript-jsx-router-playwright/tsconfig.json new file mode 100644 index 000000000..66b5e5703 --- /dev/null +++ b/playground/typescript-jsx-router-playwright/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/playground/typescript-jsx-router-playwright/tsconfig.node.json b/playground/typescript-jsx-router-playwright/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router-playwright/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router-playwright/vite.config.ts b/playground/typescript-jsx-router-playwright/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-router-playwright/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-vitest-cypress/.gitignore b/playground/typescript-jsx-router-vitest-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-router-vitest-cypress/README.md b/playground/typescript-jsx-router-vitest-cypress/README.md new file mode 100644 index 000000000..8cdb45fc0 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/README.md @@ -0,0 +1,62 @@ +# typescript-jsx-router-vitest-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-jsx-router-vitest-cypress/cypress.config.ts b/playground/typescript-jsx-router-vitest-cypress/cypress.config.ts new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/cypress.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/typescript-jsx-router-vitest-cypress/cypress/e2e/example.cy.ts b/playground/typescript-jsx-router-vitest-cypress/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-jsx-router-vitest-cypress/cypress/e2e/tsconfig.json b/playground/typescript-jsx-router-vitest-cypress/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-jsx-router-vitest-cypress/cypress/fixtures/example.json b/playground/typescript-jsx-router-vitest-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-jsx-router-vitest-cypress/cypress/support/commands.ts b/playground/typescript-jsx-router-vitest-cypress/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-jsx-router-vitest-cypress/cypress/support/e2e.ts b/playground/typescript-jsx-router-vitest-cypress/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-jsx-router-vitest-cypress/env.d.ts b/playground/typescript-jsx-router-vitest-cypress/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router-vitest-cypress/index.html b/playground/typescript-jsx-router-vitest-cypress/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router-vitest-cypress/package.json b/playground/typescript-jsx-router-vitest-cypress/package.json new file mode 100644 index 000000000..5e61eaab6 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/package.json @@ -0,0 +1,37 @@ +{ + "name": "typescript-jsx-router-vitest-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router-vitest-cypress/public/favicon.ico b/playground/typescript-jsx-router-vitest-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router-vitest-cypress/src/App.vue b/playground/typescript-jsx-router-vitest-cypress/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router-vitest-cypress/src/assets/logo.svg b/playground/typescript-jsx-router-vitest-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router-vitest-cypress/src/assets/main.css b/playground/typescript-jsx-router-vitest-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router-vitest-cypress/src/components/HelloWorld.vue b/playground/typescript-jsx-router-vitest-cypress/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router-vitest-cypress/src/components/TheWelcome.vue b/playground/typescript-jsx-router-vitest-cypress/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router-vitest-cypress/src/components/WelcomeItem.vue b/playground/typescript-jsx-router-vitest-cypress/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-router-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router-vitest-cypress/src/main.ts b/playground/typescript-jsx-router-vitest-cypress/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router-vitest-cypress/src/router/index.ts b/playground/typescript-jsx-router-vitest-cypress/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router-vitest-cypress/src/views/AboutView.vue b/playground/typescript-jsx-router-vitest-cypress/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router-vitest-cypress/src/views/HomeView.vue b/playground/typescript-jsx-router-vitest-cypress/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router-vitest-cypress/tsconfig.app.json b/playground/typescript-jsx-router-vitest-cypress/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router-vitest-cypress/tsconfig.json b/playground/typescript-jsx-router-vitest-cypress/tsconfig.json new file mode 100644 index 000000000..5304731b8 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-jsx-router-vitest-cypress/tsconfig.node.json b/playground/typescript-jsx-router-vitest-cypress/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router-vitest-cypress/tsconfig.vitest.json b/playground/typescript-jsx-router-vitest-cypress/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-router-vitest-cypress/vite.config.ts b/playground/typescript-jsx-router-vitest-cypress/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-vitest-cypress/vitest.config.ts b/playground/typescript-jsx-router-vitest-cypress/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-cypress/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-router-vitest-nightwatch/.gitignore b/playground/typescript-jsx-router-vitest-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/typescript-jsx-router-vitest-nightwatch/.vscode/extensions.json b/playground/typescript-jsx-router-vitest-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/typescript-jsx-router-vitest-nightwatch/README.md b/playground/typescript-jsx-router-vitest-nightwatch/README.md new file mode 100644 index 000000000..1617507ad --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/README.md @@ -0,0 +1,69 @@ +# typescript-jsx-router-vitest-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/typescript-jsx-router-vitest-nightwatch/env.d.ts b/playground/typescript-jsx-router-vitest-nightwatch/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router-vitest-nightwatch/index.html b/playground/typescript-jsx-router-vitest-nightwatch/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router-vitest-nightwatch/nightwatch.conf.cjs b/playground/typescript-jsx-router-vitest-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/typescript-jsx-router-vitest-nightwatch/nightwatch/nightwatch.d.ts b/playground/typescript-jsx-router-vitest-nightwatch/nightwatch/nightwatch.d.ts new file mode 100644 index 000000000..616e63f9f --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/nightwatch/nightwatch.d.ts @@ -0,0 +1,13 @@ +import { NightwatchCustomAssertions, NightwatchCustomCommands } from 'nightwatch' + +declare module 'nightwatch' { + interface NightwatchCustomAssertions { + // Add your custom assertions' types here + // elementHasCount: (selector: string, count: number) => NightwatchBrowser + } + + interface NightwatchCustomCommands { + // Add your custom commands' types here + // strictClick: (selector: string) => NightwatchBrowser + } +} diff --git a/playground/typescript-jsx-router-vitest-nightwatch/nightwatch/tsconfig.json b/playground/typescript-jsx-router-vitest-nightwatch/nightwatch/tsconfig.json new file mode 100644 index 000000000..8cd7ca1da --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/nightwatch/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "../node_modules/.tmp/tsconfig.nightwatch.tsbuildinfo", + + "target": "ESNext", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": "../", + "lib": ["ESNext", "dom"], + "types": ["nightwatch"] + }, + "include": ["../node_modules/@nightwatch/**/*", "../src/components/**/*", "../tests/e2e/**/*"], + "ts-node": { + "transpileOnly": true + }, + "files": ["nightwatch.d.ts"] +} diff --git a/playground/typescript-jsx-router-vitest-nightwatch/package.json b/playground/typescript-jsx-router-vitest-nightwatch/package.json new file mode 100644 index 000000000..3817e4954 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/package.json @@ -0,0 +1,40 @@ +{ + "name": "typescript-jsx-router-vitest-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "nightwatch tests/e2e/*", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "jsdom": "^24.0.0", + "nightwatch": "^3.4.0", + "npm-run-all2": "^6.1.2", + "ts-node": "^10.9.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router-vitest-nightwatch/public/favicon.ico b/playground/typescript-jsx-router-vitest-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router-vitest-nightwatch/src/App.vue b/playground/typescript-jsx-router-vitest-nightwatch/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router-vitest-nightwatch/src/assets/logo.svg b/playground/typescript-jsx-router-vitest-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router-vitest-nightwatch/src/assets/main.css b/playground/typescript-jsx-router-vitest-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router-vitest-nightwatch/src/components/HelloWorld.vue b/playground/typescript-jsx-router-vitest-nightwatch/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router-vitest-nightwatch/src/components/TheWelcome.vue b/playground/typescript-jsx-router-vitest-nightwatch/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router-vitest-nightwatch/src/components/WelcomeItem.vue b/playground/typescript-jsx-router-vitest-nightwatch/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-router-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router-vitest-nightwatch/src/main.ts b/playground/typescript-jsx-router-vitest-nightwatch/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router-vitest-nightwatch/src/router/index.ts b/playground/typescript-jsx-router-vitest-nightwatch/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router-vitest-nightwatch/src/views/AboutView.vue b/playground/typescript-jsx-router-vitest-nightwatch/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router-vitest-nightwatch/src/views/HomeView.vue b/playground/typescript-jsx-router-vitest-nightwatch/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router-vitest-nightwatch/tests/e2e/example.ts b/playground/typescript-jsx-router-vitest-nightwatch/tests/e2e/example.ts new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/tests/e2e/example.ts @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-jsx-router-vitest-nightwatch/tsconfig.app.json b/playground/typescript-jsx-router-vitest-nightwatch/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router-vitest-nightwatch/tsconfig.json b/playground/typescript-jsx-router-vitest-nightwatch/tsconfig.json new file mode 100644 index 000000000..a5352e667 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + }, + { + "path": "./nightwatch/tsconfig.json" + } + ] +} diff --git a/playground/typescript-jsx-router-vitest-nightwatch/tsconfig.node.json b/playground/typescript-jsx-router-vitest-nightwatch/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router-vitest-nightwatch/tsconfig.vitest.json b/playground/typescript-jsx-router-vitest-nightwatch/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-router-vitest-nightwatch/vite.config.ts b/playground/typescript-jsx-router-vitest-nightwatch/vite.config.ts new file mode 100644 index 000000000..3a6988230 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/vite.config.ts @@ -0,0 +1,20 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + nightwatchPlugin(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-vitest-nightwatch/vitest.config.ts b/playground/typescript-jsx-router-vitest-nightwatch/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-nightwatch/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-router-vitest-playwright/.gitignore b/playground/typescript-jsx-router-vitest-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/typescript-jsx-router-vitest-playwright/.vscode/extensions.json b/playground/typescript-jsx-router-vitest-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/typescript-jsx-router-vitest-playwright/README.md b/playground/typescript-jsx-router-vitest-playwright/README.md new file mode 100644 index 000000000..14a06543c --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/README.md @@ -0,0 +1,65 @@ +# typescript-jsx-router-vitest-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/typescript-jsx-router-vitest-playwright/e2e/tsconfig.json b/playground/typescript-jsx-router-vitest-playwright/e2e/tsconfig.json new file mode 100644 index 000000000..be3bbfc0e --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": ["./**/*"] +} diff --git a/playground/typescript-jsx-router-vitest-playwright/e2e/vue.spec.ts b/playground/typescript-jsx-router-vitest-playwright/e2e/vue.spec.ts new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/e2e/vue.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/typescript-jsx-router-vitest-playwright/env.d.ts b/playground/typescript-jsx-router-vitest-playwright/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router-vitest-playwright/index.html b/playground/typescript-jsx-router-vitest-playwright/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router-vitest-playwright/package.json b/playground/typescript-jsx-router-vitest-playwright/package.json new file mode 100644 index 000000000..4e79a643b --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/package.json @@ -0,0 +1,35 @@ +{ + "name": "typescript-jsx-router-vitest-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "playwright test", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router-vitest-playwright/playwright.config.ts b/playground/typescript-jsx-router-vitest-playwright/playwright.config.ts new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/playwright.config.ts @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/typescript-jsx-router-vitest-playwright/public/favicon.ico b/playground/typescript-jsx-router-vitest-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router-vitest-playwright/src/App.vue b/playground/typescript-jsx-router-vitest-playwright/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router-vitest-playwright/src/assets/logo.svg b/playground/typescript-jsx-router-vitest-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router-vitest-playwright/src/assets/main.css b/playground/typescript-jsx-router-vitest-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router-vitest-playwright/src/components/HelloWorld.vue b/playground/typescript-jsx-router-vitest-playwright/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router-vitest-playwright/src/components/TheWelcome.vue b/playground/typescript-jsx-router-vitest-playwright/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router-vitest-playwright/src/components/WelcomeItem.vue b/playground/typescript-jsx-router-vitest-playwright/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-router-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router-vitest-playwright/src/main.ts b/playground/typescript-jsx-router-vitest-playwright/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router-vitest-playwright/src/router/index.ts b/playground/typescript-jsx-router-vitest-playwright/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router-vitest-playwright/src/views/AboutView.vue b/playground/typescript-jsx-router-vitest-playwright/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router-vitest-playwright/src/views/HomeView.vue b/playground/typescript-jsx-router-vitest-playwright/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router-vitest-playwright/tsconfig.app.json b/playground/typescript-jsx-router-vitest-playwright/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router-vitest-playwright/tsconfig.json b/playground/typescript-jsx-router-vitest-playwright/tsconfig.json new file mode 100644 index 000000000..100cf6a8f --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ] +} diff --git a/playground/typescript-jsx-router-vitest-playwright/tsconfig.node.json b/playground/typescript-jsx-router-vitest-playwright/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router-vitest-playwright/tsconfig.vitest.json b/playground/typescript-jsx-router-vitest-playwright/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-router-vitest-playwright/vite.config.ts b/playground/typescript-jsx-router-vitest-playwright/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-vitest-playwright/vitest.config.ts b/playground/typescript-jsx-router-vitest-playwright/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-router-vitest-playwright/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-router-vitest/.gitignore b/playground/typescript-jsx-router-vitest/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-router-vitest/README.md b/playground/typescript-jsx-router-vitest/README.md new file mode 100644 index 000000000..51d21c67d --- /dev/null +++ b/playground/typescript-jsx-router-vitest/README.md @@ -0,0 +1,46 @@ +# typescript-jsx-router-vitest + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` diff --git a/playground/typescript-jsx-router-vitest/env.d.ts b/playground/typescript-jsx-router-vitest/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router-vitest/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router-vitest/index.html b/playground/typescript-jsx-router-vitest/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router-vitest/package.json b/playground/typescript-jsx-router-vitest/package.json new file mode 100644 index 000000000..163fc1038 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/package.json @@ -0,0 +1,33 @@ +{ + "name": "typescript-jsx-router-vitest", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router-vitest/public/favicon.ico b/playground/typescript-jsx-router-vitest/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router-vitest/src/App.vue b/playground/typescript-jsx-router-vitest/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router-vitest/src/assets/logo.svg b/playground/typescript-jsx-router-vitest/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router-vitest/src/assets/main.css b/playground/typescript-jsx-router-vitest/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router-vitest/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router-vitest/src/components/HelloWorld.vue b/playground/typescript-jsx-router-vitest/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router-vitest/src/components/TheWelcome.vue b/playground/typescript-jsx-router-vitest/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router-vitest/src/components/WelcomeItem.vue b/playground/typescript-jsx-router-vitest/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router-vitest/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router-vitest/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-router-vitest/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-router-vitest/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router-vitest/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-vitest/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router-vitest/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router-vitest/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-vitest/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router-vitest/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router-vitest/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-vitest/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router-vitest/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-vitest/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router-vitest/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router-vitest/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router-vitest/src/main.ts b/playground/typescript-jsx-router-vitest/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router-vitest/src/router/index.ts b/playground/typescript-jsx-router-vitest/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router-vitest/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router-vitest/src/views/AboutView.vue b/playground/typescript-jsx-router-vitest/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router-vitest/src/views/HomeView.vue b/playground/typescript-jsx-router-vitest/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router-vitest/tsconfig.app.json b/playground/typescript-jsx-router-vitest/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router-vitest/tsconfig.json b/playground/typescript-jsx-router-vitest/tsconfig.json new file mode 100644 index 000000000..100cf6a8f --- /dev/null +++ b/playground/typescript-jsx-router-vitest/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ] +} diff --git a/playground/typescript-jsx-router-vitest/tsconfig.node.json b/playground/typescript-jsx-router-vitest/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router-vitest/tsconfig.vitest.json b/playground/typescript-jsx-router-vitest/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-router-vitest/vite.config.ts b/playground/typescript-jsx-router-vitest/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-vitest/vitest.config.ts b/playground/typescript-jsx-router-vitest/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-router-vitest/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-router-with-tests/.gitignore b/playground/typescript-jsx-router-with-tests/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-router-with-tests/README.md b/playground/typescript-jsx-router-with-tests/README.md new file mode 100644 index 000000000..f51d0abc6 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/README.md @@ -0,0 +1,62 @@ +# typescript-jsx-router-with-tests + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-jsx-router-with-tests/cypress.config.ts b/playground/typescript-jsx-router-with-tests/cypress.config.ts new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/cypress.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/typescript-jsx-router-with-tests/cypress/e2e/example.cy.ts b/playground/typescript-jsx-router-with-tests/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-jsx-router-with-tests/cypress/e2e/tsconfig.json b/playground/typescript-jsx-router-with-tests/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-jsx-router-with-tests/cypress/fixtures/example.json b/playground/typescript-jsx-router-with-tests/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-jsx-router-with-tests/cypress/support/commands.ts b/playground/typescript-jsx-router-with-tests/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-jsx-router-with-tests/cypress/support/e2e.ts b/playground/typescript-jsx-router-with-tests/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-jsx-router-with-tests/env.d.ts b/playground/typescript-jsx-router-with-tests/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router-with-tests/index.html b/playground/typescript-jsx-router-with-tests/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router-with-tests/package.json b/playground/typescript-jsx-router-with-tests/package.json new file mode 100644 index 000000000..ece91193e --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/package.json @@ -0,0 +1,37 @@ +{ + "name": "typescript-jsx-router-with-tests", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router-with-tests/public/favicon.ico b/playground/typescript-jsx-router-with-tests/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router-with-tests/src/App.vue b/playground/typescript-jsx-router-with-tests/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router-with-tests/src/assets/logo.svg b/playground/typescript-jsx-router-with-tests/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router-with-tests/src/assets/main.css b/playground/typescript-jsx-router-with-tests/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router-with-tests/src/components/HelloWorld.vue b/playground/typescript-jsx-router-with-tests/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router-with-tests/src/components/TheWelcome.vue b/playground/typescript-jsx-router-with-tests/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router-with-tests/src/components/WelcomeItem.vue b/playground/typescript-jsx-router-with-tests/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router-with-tests/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-router-with-tests/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-router-with-tests/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router-with-tests/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-with-tests/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router-with-tests/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-with-tests/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router-with-tests/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-with-tests/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router-with-tests/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router-with-tests/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router-with-tests/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router-with-tests/src/main.ts b/playground/typescript-jsx-router-with-tests/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router-with-tests/src/router/index.ts b/playground/typescript-jsx-router-with-tests/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router-with-tests/src/views/AboutView.vue b/playground/typescript-jsx-router-with-tests/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router-with-tests/src/views/HomeView.vue b/playground/typescript-jsx-router-with-tests/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router-with-tests/tsconfig.app.json b/playground/typescript-jsx-router-with-tests/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router-with-tests/tsconfig.json b/playground/typescript-jsx-router-with-tests/tsconfig.json new file mode 100644 index 000000000..5304731b8 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-jsx-router-with-tests/tsconfig.node.json b/playground/typescript-jsx-router-with-tests/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router-with-tests/tsconfig.vitest.json b/playground/typescript-jsx-router-with-tests/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-router-with-tests/vite.config.ts b/playground/typescript-jsx-router-with-tests/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-router-with-tests/vitest.config.ts b/playground/typescript-jsx-router-with-tests/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-router-with-tests/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-router/.gitignore b/playground/typescript-jsx-router/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-router/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-router/README.md b/playground/typescript-jsx-router/README.md new file mode 100644 index 000000000..1b2c57111 --- /dev/null +++ b/playground/typescript-jsx-router/README.md @@ -0,0 +1,40 @@ +# typescript-jsx-router + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` diff --git a/playground/typescript-jsx-router/env.d.ts b/playground/typescript-jsx-router/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-router/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-router/index.html b/playground/typescript-jsx-router/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-router/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-router/package.json b/playground/typescript-jsx-router/package.json new file mode 100644 index 000000000..6b93101ae --- /dev/null +++ b/playground/typescript-jsx-router/package.json @@ -0,0 +1,28 @@ +{ + "name": "typescript-jsx-router", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-router/public/favicon.ico b/playground/typescript-jsx-router/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-router/src/App.vue b/playground/typescript-jsx-router/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-jsx-router/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-jsx-router/src/assets/logo.svg b/playground/typescript-jsx-router/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-router/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-router/src/assets/main.css b/playground/typescript-jsx-router/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-router/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-router/src/components/HelloWorld.vue b/playground/typescript-jsx-router/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-jsx-router/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-jsx-router/src/components/TheWelcome.vue b/playground/typescript-jsx-router/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-jsx-router/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-jsx-router/src/components/WelcomeItem.vue b/playground/typescript-jsx-router/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-jsx-router/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-jsx-router/src/components/icons/IconCommunity.vue b/playground/typescript-jsx-router/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-jsx-router/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router/src/components/icons/IconDocumentation.vue b/playground/typescript-jsx-router/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-jsx-router/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router/src/components/icons/IconEcosystem.vue b/playground/typescript-jsx-router/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-jsx-router/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router/src/components/icons/IconSupport.vue b/playground/typescript-jsx-router/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-jsx-router/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-jsx-router/src/components/icons/IconTooling.vue b/playground/typescript-jsx-router/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-jsx-router/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-jsx-router/src/main.ts b/playground/typescript-jsx-router/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-jsx-router/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-jsx-router/src/router/index.ts b/playground/typescript-jsx-router/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-jsx-router/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-jsx-router/src/views/AboutView.vue b/playground/typescript-jsx-router/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-jsx-router/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-jsx-router/src/views/HomeView.vue b/playground/typescript-jsx-router/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-jsx-router/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-jsx-router/tsconfig.app.json b/playground/typescript-jsx-router/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-router/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-router/tsconfig.json b/playground/typescript-jsx-router/tsconfig.json new file mode 100644 index 000000000..66b5e5703 --- /dev/null +++ b/playground/typescript-jsx-router/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/playground/typescript-jsx-router/tsconfig.node.json b/playground/typescript-jsx-router/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-router/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-router/vite.config.ts b/playground/typescript-jsx-router/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-router/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-vitest-cypress/.gitignore b/playground/typescript-jsx-vitest-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-vitest-cypress/README.md b/playground/typescript-jsx-vitest-cypress/README.md new file mode 100644 index 000000000..69d98a5c1 --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/README.md @@ -0,0 +1,62 @@ +# typescript-jsx-vitest-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-jsx-vitest-cypress/cypress.config.ts b/playground/typescript-jsx-vitest-cypress/cypress.config.ts new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/cypress.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/typescript-jsx-vitest-cypress/cypress/e2e/example.cy.ts b/playground/typescript-jsx-vitest-cypress/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-jsx-vitest-cypress/cypress/e2e/tsconfig.json b/playground/typescript-jsx-vitest-cypress/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-jsx-vitest-cypress/cypress/fixtures/example.json b/playground/typescript-jsx-vitest-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-jsx-vitest-cypress/cypress/support/commands.ts b/playground/typescript-jsx-vitest-cypress/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-jsx-vitest-cypress/cypress/support/e2e.ts b/playground/typescript-jsx-vitest-cypress/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-jsx-vitest-cypress/env.d.ts b/playground/typescript-jsx-vitest-cypress/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-vitest-cypress/index.html b/playground/typescript-jsx-vitest-cypress/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-vitest-cypress/package.json b/playground/typescript-jsx-vitest-cypress/package.json new file mode 100644 index 000000000..effc00243 --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/package.json @@ -0,0 +1,36 @@ +{ + "name": "typescript-jsx-vitest-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-vitest-cypress/public/favicon.ico b/playground/typescript-jsx-vitest-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-vitest-cypress/src/App.vue b/playground/typescript-jsx-vitest-cypress/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx-vitest-cypress/src/assets/logo.svg b/playground/typescript-jsx-vitest-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-vitest-cypress/src/assets/main.css b/playground/typescript-jsx-vitest-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-vitest-cypress/src/main.ts b/playground/typescript-jsx-vitest-cypress/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript-jsx-vitest-cypress/tsconfig.app.json b/playground/typescript-jsx-vitest-cypress/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-vitest-cypress/tsconfig.json b/playground/typescript-jsx-vitest-cypress/tsconfig.json new file mode 100644 index 000000000..5304731b8 --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-jsx-vitest-cypress/tsconfig.node.json b/playground/typescript-jsx-vitest-cypress/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-vitest-cypress/tsconfig.vitest.json b/playground/typescript-jsx-vitest-cypress/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-vitest-cypress/vite.config.ts b/playground/typescript-jsx-vitest-cypress/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-vitest-cypress/vitest.config.ts b/playground/typescript-jsx-vitest-cypress/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-vitest-cypress/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-vitest-nightwatch/.gitignore b/playground/typescript-jsx-vitest-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/typescript-jsx-vitest-nightwatch/.vscode/extensions.json b/playground/typescript-jsx-vitest-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/typescript-jsx-vitest-nightwatch/README.md b/playground/typescript-jsx-vitest-nightwatch/README.md new file mode 100644 index 000000000..c4dbab749 --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/README.md @@ -0,0 +1,69 @@ +# typescript-jsx-vitest-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/typescript-jsx-vitest-nightwatch/env.d.ts b/playground/typescript-jsx-vitest-nightwatch/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-vitest-nightwatch/index.html b/playground/typescript-jsx-vitest-nightwatch/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-vitest-nightwatch/nightwatch.conf.cjs b/playground/typescript-jsx-vitest-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/typescript-jsx-vitest-nightwatch/nightwatch/nightwatch.d.ts b/playground/typescript-jsx-vitest-nightwatch/nightwatch/nightwatch.d.ts new file mode 100644 index 000000000..616e63f9f --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/nightwatch/nightwatch.d.ts @@ -0,0 +1,13 @@ +import { NightwatchCustomAssertions, NightwatchCustomCommands } from 'nightwatch' + +declare module 'nightwatch' { + interface NightwatchCustomAssertions { + // Add your custom assertions' types here + // elementHasCount: (selector: string, count: number) => NightwatchBrowser + } + + interface NightwatchCustomCommands { + // Add your custom commands' types here + // strictClick: (selector: string) => NightwatchBrowser + } +} diff --git a/playground/typescript-jsx-vitest-nightwatch/nightwatch/tsconfig.json b/playground/typescript-jsx-vitest-nightwatch/nightwatch/tsconfig.json new file mode 100644 index 000000000..8cd7ca1da --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/nightwatch/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "../node_modules/.tmp/tsconfig.nightwatch.tsbuildinfo", + + "target": "ESNext", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": "../", + "lib": ["ESNext", "dom"], + "types": ["nightwatch"] + }, + "include": ["../node_modules/@nightwatch/**/*", "../src/components/**/*", "../tests/e2e/**/*"], + "ts-node": { + "transpileOnly": true + }, + "files": ["nightwatch.d.ts"] +} diff --git a/playground/typescript-jsx-vitest-nightwatch/package.json b/playground/typescript-jsx-vitest-nightwatch/package.json new file mode 100644 index 000000000..75d98022d --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/package.json @@ -0,0 +1,39 @@ +{ + "name": "typescript-jsx-vitest-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "nightwatch tests/e2e/*", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "jsdom": "^24.0.0", + "nightwatch": "^3.4.0", + "npm-run-all2": "^6.1.2", + "ts-node": "^10.9.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-vitest-nightwatch/public/favicon.ico b/playground/typescript-jsx-vitest-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-vitest-nightwatch/src/App.vue b/playground/typescript-jsx-vitest-nightwatch/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx-vitest-nightwatch/src/assets/logo.svg b/playground/typescript-jsx-vitest-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-vitest-nightwatch/src/assets/main.css b/playground/typescript-jsx-vitest-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-vitest-nightwatch/src/main.ts b/playground/typescript-jsx-vitest-nightwatch/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript-jsx-vitest-nightwatch/tests/e2e/example.ts b/playground/typescript-jsx-vitest-nightwatch/tests/e2e/example.ts new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/tests/e2e/example.ts @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-jsx-vitest-nightwatch/tsconfig.app.json b/playground/typescript-jsx-vitest-nightwatch/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-vitest-nightwatch/tsconfig.json b/playground/typescript-jsx-vitest-nightwatch/tsconfig.json new file mode 100644 index 000000000..a5352e667 --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + }, + { + "path": "./nightwatch/tsconfig.json" + } + ] +} diff --git a/playground/typescript-jsx-vitest-nightwatch/tsconfig.node.json b/playground/typescript-jsx-vitest-nightwatch/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-vitest-nightwatch/tsconfig.vitest.json b/playground/typescript-jsx-vitest-nightwatch/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-vitest-nightwatch/vite.config.ts b/playground/typescript-jsx-vitest-nightwatch/vite.config.ts new file mode 100644 index 000000000..3a6988230 --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/vite.config.ts @@ -0,0 +1,20 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + nightwatchPlugin(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-vitest-nightwatch/vitest.config.ts b/playground/typescript-jsx-vitest-nightwatch/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-vitest-nightwatch/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-vitest-playwright/.gitignore b/playground/typescript-jsx-vitest-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/typescript-jsx-vitest-playwright/.vscode/extensions.json b/playground/typescript-jsx-vitest-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/typescript-jsx-vitest-playwright/README.md b/playground/typescript-jsx-vitest-playwright/README.md new file mode 100644 index 000000000..94b71b51e --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/README.md @@ -0,0 +1,65 @@ +# typescript-jsx-vitest-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/typescript-jsx-vitest-playwright/e2e/tsconfig.json b/playground/typescript-jsx-vitest-playwright/e2e/tsconfig.json new file mode 100644 index 000000000..be3bbfc0e --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": ["./**/*"] +} diff --git a/playground/typescript-jsx-vitest-playwright/e2e/vue.spec.ts b/playground/typescript-jsx-vitest-playwright/e2e/vue.spec.ts new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/e2e/vue.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/typescript-jsx-vitest-playwright/env.d.ts b/playground/typescript-jsx-vitest-playwright/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-vitest-playwright/index.html b/playground/typescript-jsx-vitest-playwright/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-vitest-playwright/package.json b/playground/typescript-jsx-vitest-playwright/package.json new file mode 100644 index 000000000..22cba2a5a --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/package.json @@ -0,0 +1,34 @@ +{ + "name": "typescript-jsx-vitest-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "playwright test", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-vitest-playwright/playwright.config.ts b/playground/typescript-jsx-vitest-playwright/playwright.config.ts new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/playwright.config.ts @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/typescript-jsx-vitest-playwright/public/favicon.ico b/playground/typescript-jsx-vitest-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-vitest-playwright/src/App.vue b/playground/typescript-jsx-vitest-playwright/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx-vitest-playwright/src/assets/logo.svg b/playground/typescript-jsx-vitest-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-vitest-playwright/src/assets/main.css b/playground/typescript-jsx-vitest-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-vitest-playwright/src/main.ts b/playground/typescript-jsx-vitest-playwright/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript-jsx-vitest-playwright/tsconfig.app.json b/playground/typescript-jsx-vitest-playwright/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-vitest-playwright/tsconfig.json b/playground/typescript-jsx-vitest-playwright/tsconfig.json new file mode 100644 index 000000000..100cf6a8f --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ] +} diff --git a/playground/typescript-jsx-vitest-playwright/tsconfig.node.json b/playground/typescript-jsx-vitest-playwright/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-vitest-playwright/tsconfig.vitest.json b/playground/typescript-jsx-vitest-playwright/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-vitest-playwright/vite.config.ts b/playground/typescript-jsx-vitest-playwright/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-vitest-playwright/vitest.config.ts b/playground/typescript-jsx-vitest-playwright/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-vitest-playwright/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-vitest/.gitignore b/playground/typescript-jsx-vitest/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-vitest/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-vitest/README.md b/playground/typescript-jsx-vitest/README.md new file mode 100644 index 000000000..9c8e9f019 --- /dev/null +++ b/playground/typescript-jsx-vitest/README.md @@ -0,0 +1,46 @@ +# typescript-jsx-vitest + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` diff --git a/playground/typescript-jsx-vitest/env.d.ts b/playground/typescript-jsx-vitest/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-vitest/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-vitest/index.html b/playground/typescript-jsx-vitest/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-vitest/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-vitest/package.json b/playground/typescript-jsx-vitest/package.json new file mode 100644 index 000000000..88cc6aa9c --- /dev/null +++ b/playground/typescript-jsx-vitest/package.json @@ -0,0 +1,32 @@ +{ + "name": "typescript-jsx-vitest", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-vitest/public/favicon.ico b/playground/typescript-jsx-vitest/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-vitest/src/App.vue b/playground/typescript-jsx-vitest/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx-vitest/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx-vitest/src/assets/logo.svg b/playground/typescript-jsx-vitest/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-vitest/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-vitest/src/assets/main.css b/playground/typescript-jsx-vitest/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-vitest/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-vitest/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-vitest/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-vitest/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-vitest/src/main.ts b/playground/typescript-jsx-vitest/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript-jsx-vitest/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript-jsx-vitest/tsconfig.app.json b/playground/typescript-jsx-vitest/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-vitest/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-vitest/tsconfig.json b/playground/typescript-jsx-vitest/tsconfig.json new file mode 100644 index 000000000..100cf6a8f --- /dev/null +++ b/playground/typescript-jsx-vitest/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ] +} diff --git a/playground/typescript-jsx-vitest/tsconfig.node.json b/playground/typescript-jsx-vitest/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-vitest/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-vitest/tsconfig.vitest.json b/playground/typescript-jsx-vitest/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-vitest/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-vitest/vite.config.ts b/playground/typescript-jsx-vitest/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-vitest/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-vitest/vitest.config.ts b/playground/typescript-jsx-vitest/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-vitest/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx-with-tests/.gitignore b/playground/typescript-jsx-with-tests/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx-with-tests/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx-with-tests/README.md b/playground/typescript-jsx-with-tests/README.md new file mode 100644 index 000000000..efb96d69e --- /dev/null +++ b/playground/typescript-jsx-with-tests/README.md @@ -0,0 +1,62 @@ +# typescript-jsx-with-tests + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-jsx-with-tests/cypress.config.ts b/playground/typescript-jsx-with-tests/cypress.config.ts new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/typescript-jsx-with-tests/cypress.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/typescript-jsx-with-tests/cypress/e2e/example.cy.ts b/playground/typescript-jsx-with-tests/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-jsx-with-tests/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-jsx-with-tests/cypress/e2e/tsconfig.json b/playground/typescript-jsx-with-tests/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-jsx-with-tests/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-jsx-with-tests/cypress/fixtures/example.json b/playground/typescript-jsx-with-tests/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-jsx-with-tests/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-jsx-with-tests/cypress/support/commands.ts b/playground/typescript-jsx-with-tests/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-jsx-with-tests/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-jsx-with-tests/cypress/support/e2e.ts b/playground/typescript-jsx-with-tests/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-jsx-with-tests/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-jsx-with-tests/env.d.ts b/playground/typescript-jsx-with-tests/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx-with-tests/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx-with-tests/index.html b/playground/typescript-jsx-with-tests/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx-with-tests/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx-with-tests/package.json b/playground/typescript-jsx-with-tests/package.json new file mode 100644 index 000000000..10095b811 --- /dev/null +++ b/playground/typescript-jsx-with-tests/package.json @@ -0,0 +1,36 @@ +{ + "name": "typescript-jsx-with-tests", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx-with-tests/public/favicon.ico b/playground/typescript-jsx-with-tests/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx-with-tests/src/App.vue b/playground/typescript-jsx-with-tests/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx-with-tests/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx-with-tests/src/assets/logo.svg b/playground/typescript-jsx-with-tests/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx-with-tests/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx-with-tests/src/assets/main.css b/playground/typescript-jsx-with-tests/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx-with-tests/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx-with-tests/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-jsx-with-tests/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-jsx-with-tests/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-jsx-with-tests/src/main.ts b/playground/typescript-jsx-with-tests/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript-jsx-with-tests/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript-jsx-with-tests/tsconfig.app.json b/playground/typescript-jsx-with-tests/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx-with-tests/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx-with-tests/tsconfig.json b/playground/typescript-jsx-with-tests/tsconfig.json new file mode 100644 index 000000000..5304731b8 --- /dev/null +++ b/playground/typescript-jsx-with-tests/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-jsx-with-tests/tsconfig.node.json b/playground/typescript-jsx-with-tests/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx-with-tests/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx-with-tests/tsconfig.vitest.json b/playground/typescript-jsx-with-tests/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-jsx-with-tests/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-jsx-with-tests/vite.config.ts b/playground/typescript-jsx-with-tests/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx-with-tests/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-jsx-with-tests/vitest.config.ts b/playground/typescript-jsx-with-tests/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-jsx-with-tests/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-jsx/.gitignore b/playground/typescript-jsx/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-jsx/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-jsx/README.md b/playground/typescript-jsx/README.md new file mode 100644 index 000000000..09436e2ea --- /dev/null +++ b/playground/typescript-jsx/README.md @@ -0,0 +1,40 @@ +# typescript-jsx + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` diff --git a/playground/typescript-jsx/env.d.ts b/playground/typescript-jsx/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-jsx/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-jsx/index.html b/playground/typescript-jsx/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-jsx/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-jsx/package.json b/playground/typescript-jsx/package.json new file mode 100644 index 000000000..1821c162d --- /dev/null +++ b/playground/typescript-jsx/package.json @@ -0,0 +1,27 @@ +{ + "name": "typescript-jsx", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vitejs/plugin-vue-jsx": "^3.1.0", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-jsx/public/favicon.ico b/playground/typescript-jsx/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-jsx/src/App.vue b/playground/typescript-jsx/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-jsx/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-jsx/src/assets/logo.svg b/playground/typescript-jsx/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-jsx/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-jsx/src/assets/main.css b/playground/typescript-jsx/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-jsx/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-jsx/src/main.ts b/playground/typescript-jsx/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript-jsx/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript-jsx/tsconfig.app.json b/playground/typescript-jsx/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-jsx/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-jsx/tsconfig.json b/playground/typescript-jsx/tsconfig.json new file mode 100644 index 000000000..66b5e5703 --- /dev/null +++ b/playground/typescript-jsx/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/playground/typescript-jsx/tsconfig.node.json b/playground/typescript-jsx/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-jsx/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-jsx/vite.config.ts b/playground/typescript-jsx/vite.config.ts new file mode 100644 index 000000000..36c618756 --- /dev/null +++ b/playground/typescript-jsx/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-nightwatch/.gitignore b/playground/typescript-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/typescript-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/typescript-nightwatch/.vscode/extensions.json b/playground/typescript-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/typescript-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/typescript-nightwatch/README.md b/playground/typescript-nightwatch/README.md new file mode 100644 index 000000000..e9ca024d3 --- /dev/null +++ b/playground/typescript-nightwatch/README.md @@ -0,0 +1,63 @@ +# typescript-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/typescript-nightwatch/env.d.ts b/playground/typescript-nightwatch/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-nightwatch/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-nightwatch/index.html b/playground/typescript-nightwatch/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-nightwatch/nightwatch.conf.cjs b/playground/typescript-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/typescript-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/typescript-nightwatch/nightwatch/index.html b/playground/typescript-nightwatch/nightwatch/index.html new file mode 100644 index 000000000..b7e1ec765 --- /dev/null +++ b/playground/typescript-nightwatch/nightwatch/index.html @@ -0,0 +1,16 @@ + + + + + + + + + Vue Renderer + + + +
+ + + diff --git a/playground/typescript-nightwatch/nightwatch/nightwatch.d.ts b/playground/typescript-nightwatch/nightwatch/nightwatch.d.ts new file mode 100644 index 000000000..616e63f9f --- /dev/null +++ b/playground/typescript-nightwatch/nightwatch/nightwatch.d.ts @@ -0,0 +1,13 @@ +import { NightwatchCustomAssertions, NightwatchCustomCommands } from 'nightwatch' + +declare module 'nightwatch' { + interface NightwatchCustomAssertions { + // Add your custom assertions' types here + // elementHasCount: (selector: string, count: number) => NightwatchBrowser + } + + interface NightwatchCustomCommands { + // Add your custom commands' types here + // strictClick: (selector: string) => NightwatchBrowser + } +} diff --git a/playground/typescript-nightwatch/nightwatch/tsconfig.json b/playground/typescript-nightwatch/nightwatch/tsconfig.json new file mode 100644 index 000000000..8cd7ca1da --- /dev/null +++ b/playground/typescript-nightwatch/nightwatch/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "../node_modules/.tmp/tsconfig.nightwatch.tsbuildinfo", + + "target": "ESNext", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": "../", + "lib": ["ESNext", "dom"], + "types": ["nightwatch"] + }, + "include": ["../node_modules/@nightwatch/**/*", "../src/components/**/*", "../tests/e2e/**/*"], + "ts-node": { + "transpileOnly": true + }, + "files": ["nightwatch.d.ts"] +} diff --git a/playground/typescript-nightwatch/package.json b/playground/typescript-nightwatch/package.json new file mode 100644 index 000000000..e67792604 --- /dev/null +++ b/playground/typescript-nightwatch/package.json @@ -0,0 +1,35 @@ +{ + "name": "typescript-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "nightwatch tests/e2e/*", + "test:unit": "nightwatch src/**/__tests__/*", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "nightwatch": "^3.4.0", + "npm-run-all2": "^6.1.2", + "ts-node": "^10.9.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-nightwatch/public/favicon.ico b/playground/typescript-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-nightwatch/src/App.vue b/playground/typescript-nightwatch/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-nightwatch/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-nightwatch/src/assets/logo.svg b/playground/typescript-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-nightwatch/src/assets/main.css b/playground/typescript-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-nightwatch/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-nightwatch/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..810641e6e --- /dev/null +++ b/playground/typescript-nightwatch/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,14 @@ +describe('Hello World', function () { + before((browser) => { + browser.init() + }) + + it('renders properly', async function () { + const welcomeComponent = await browser.mountComponent('/src/components/HelloWorld.vue', {props: {msg: 'Hello Nightwatch'}}); + + browser.expect.element(welcomeComponent).to.be.present; + browser.expect.element('h1').text.to.contain('Hello Nightwatch'); + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-nightwatch/src/main.ts b/playground/typescript-nightwatch/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript-nightwatch/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript-nightwatch/tests/e2e/example.ts b/playground/typescript-nightwatch/tests/e2e/example.ts new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/typescript-nightwatch/tests/e2e/example.ts @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-nightwatch/tsconfig.app.json b/playground/typescript-nightwatch/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-nightwatch/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-nightwatch/tsconfig.json b/playground/typescript-nightwatch/tsconfig.json new file mode 100644 index 000000000..5c385ae2c --- /dev/null +++ b/playground/typescript-nightwatch/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./nightwatch/tsconfig.json" + } + ] +} diff --git a/playground/typescript-nightwatch/tsconfig.node.json b/playground/typescript-nightwatch/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-nightwatch/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-nightwatch/vite.config.ts b/playground/typescript-nightwatch/vite.config.ts new file mode 100644 index 000000000..fd83c5b21 --- /dev/null +++ b/playground/typescript-nightwatch/vite.config.ts @@ -0,0 +1,20 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + nightwatchPlugin({ + renderPage: './nightwatch/index.html' + }), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-pinia-cypress/.gitignore b/playground/typescript-pinia-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-pinia-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-pinia-cypress/README.md b/playground/typescript-pinia-cypress/README.md new file mode 100644 index 000000000..e0d8690a5 --- /dev/null +++ b/playground/typescript-pinia-cypress/README.md @@ -0,0 +1,62 @@ +# typescript-pinia-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Headed Component Tests with [Cypress Component Testing](https://on.cypress.io/component) + +```sh +pnpm test:unit:dev # or `pnpm test:unit` for headless testing +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-pinia-cypress/cypress.config.ts b/playground/typescript-pinia-cypress/cypress.config.ts new file mode 100644 index 000000000..c8fac1298 --- /dev/null +++ b/playground/typescript-pinia-cypress/cypress.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + }, + component: { + specPattern: 'src/**/__tests__/*.{cy,spec}.{js,ts,jsx,tsx}', + devServer: { + framework: 'vue', + bundler: 'vite' + } + } +}) diff --git a/playground/typescript-pinia-cypress/cypress/e2e/example.cy.ts b/playground/typescript-pinia-cypress/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-pinia-cypress/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-pinia-cypress/cypress/e2e/tsconfig.json b/playground/typescript-pinia-cypress/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-pinia-cypress/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-pinia-cypress/cypress/fixtures/example.json b/playground/typescript-pinia-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-pinia-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-pinia-cypress/cypress/support/commands.ts b/playground/typescript-pinia-cypress/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-pinia-cypress/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-pinia-cypress/cypress/support/component-index.html b/playground/typescript-pinia-cypress/cypress/support/component-index.html new file mode 100644 index 000000000..5f9622ae2 --- /dev/null +++ b/playground/typescript-pinia-cypress/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + Components App + + +
+ + diff --git a/playground/typescript-pinia-cypress/cypress/support/component.ts b/playground/typescript-pinia-cypress/cypress/support/component.ts new file mode 100644 index 000000000..04e4c352b --- /dev/null +++ b/playground/typescript-pinia-cypress/cypress/support/component.ts @@ -0,0 +1,43 @@ +// *********************************************************** +// This example support/component.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') + +// Import global styles +import '@/assets/main.css' + +import { mount } from 'cypress/vue' + +// Augment the Cypress namespace to include type definitions for +// your custom command. +// Alternatively, can be defined in cypress/support/component.d.ts +// with a at the top of your spec. +/* eslint-disable @typescript-eslint/no-namespace */ +declare global { + namespace Cypress { + interface Chainable { + mount: typeof mount + } + } +} + +Cypress.Commands.add('mount', mount) + +// Example use: +// cy.mount(MyComponent) diff --git a/playground/typescript-pinia-cypress/cypress/support/e2e.ts b/playground/typescript-pinia-cypress/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-pinia-cypress/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-pinia-cypress/env.d.ts b/playground/typescript-pinia-cypress/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-pinia-cypress/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-pinia-cypress/index.html b/playground/typescript-pinia-cypress/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-pinia-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-pinia-cypress/package.json b/playground/typescript-pinia-cypress/package.json new file mode 100644 index 000000000..bd188ba76 --- /dev/null +++ b/playground/typescript-pinia-cypress/package.json @@ -0,0 +1,33 @@ +{ + "name": "typescript-pinia-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "test:unit": "cypress run --component", + "test:unit:dev": "cypress open --component", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-pinia-cypress/public/favicon.ico b/playground/typescript-pinia-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-pinia-cypress/src/App.vue b/playground/typescript-pinia-cypress/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-pinia-cypress/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-pinia-cypress/src/assets/logo.svg b/playground/typescript-pinia-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-pinia-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-pinia-cypress/src/assets/main.css b/playground/typescript-pinia-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-pinia-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-pinia-cypress/src/components/__tests__/HelloWorld.cy.ts b/playground/typescript-pinia-cypress/src/components/__tests__/HelloWorld.cy.ts new file mode 100644 index 000000000..535a0e51c --- /dev/null +++ b/playground/typescript-pinia-cypress/src/components/__tests__/HelloWorld.cy.ts @@ -0,0 +1,12 @@ +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('playground', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + }) + + it('renders properly', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + cy.get('h1').should('contain', 'Hello Cypress') + }) +}) diff --git a/playground/typescript-pinia-cypress/src/main.ts b/playground/typescript-pinia-cypress/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-pinia-cypress/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-pinia-cypress/src/stores/counter.ts b/playground/typescript-pinia-cypress/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-pinia-cypress/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-pinia-cypress/tsconfig.app.json b/playground/typescript-pinia-cypress/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-pinia-cypress/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-pinia-cypress/tsconfig.cypress-ct.json b/playground/typescript-pinia-cypress/tsconfig.cypress-ct.json new file mode 100644 index 000000000..12833b275 --- /dev/null +++ b/playground/typescript-pinia-cypress/tsconfig.cypress-ct.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.app.json", + "include": [ + "env.d.ts", + "src/**/*", + "src/**/*.vue", + "cypress/support/component.*", + "cypress/support/commands.ts" + ], + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.cypress-ct.tsbuildinfo" + } +} diff --git a/playground/typescript-pinia-cypress/tsconfig.json b/playground/typescript-pinia-cypress/tsconfig.json new file mode 100644 index 000000000..d3b6c3172 --- /dev/null +++ b/playground/typescript-pinia-cypress/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.cypress-ct.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-pinia-cypress/tsconfig.node.json b/playground/typescript-pinia-cypress/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-pinia-cypress/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-pinia-cypress/vite.config.ts b/playground/typescript-pinia-cypress/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-pinia-cypress/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-pinia-nightwatch/.gitignore b/playground/typescript-pinia-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/typescript-pinia-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/typescript-pinia-nightwatch/.vscode/extensions.json b/playground/typescript-pinia-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/typescript-pinia-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/typescript-pinia-nightwatch/README.md b/playground/typescript-pinia-nightwatch/README.md new file mode 100644 index 000000000..8f6468d6b --- /dev/null +++ b/playground/typescript-pinia-nightwatch/README.md @@ -0,0 +1,63 @@ +# typescript-pinia-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/typescript-pinia-nightwatch/env.d.ts b/playground/typescript-pinia-nightwatch/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-pinia-nightwatch/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-pinia-nightwatch/index.html b/playground/typescript-pinia-nightwatch/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-pinia-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-pinia-nightwatch/nightwatch.conf.cjs b/playground/typescript-pinia-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/typescript-pinia-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/typescript-pinia-nightwatch/nightwatch/index.html b/playground/typescript-pinia-nightwatch/nightwatch/index.html new file mode 100644 index 000000000..b7e1ec765 --- /dev/null +++ b/playground/typescript-pinia-nightwatch/nightwatch/index.html @@ -0,0 +1,16 @@ + + + + + + + + + Vue Renderer + + + +
+ + + diff --git a/playground/typescript-pinia-nightwatch/nightwatch/nightwatch.d.ts b/playground/typescript-pinia-nightwatch/nightwatch/nightwatch.d.ts new file mode 100644 index 000000000..616e63f9f --- /dev/null +++ b/playground/typescript-pinia-nightwatch/nightwatch/nightwatch.d.ts @@ -0,0 +1,13 @@ +import { NightwatchCustomAssertions, NightwatchCustomCommands } from 'nightwatch' + +declare module 'nightwatch' { + interface NightwatchCustomAssertions { + // Add your custom assertions' types here + // elementHasCount: (selector: string, count: number) => NightwatchBrowser + } + + interface NightwatchCustomCommands { + // Add your custom commands' types here + // strictClick: (selector: string) => NightwatchBrowser + } +} diff --git a/playground/typescript-pinia-nightwatch/nightwatch/tsconfig.json b/playground/typescript-pinia-nightwatch/nightwatch/tsconfig.json new file mode 100644 index 000000000..8cd7ca1da --- /dev/null +++ b/playground/typescript-pinia-nightwatch/nightwatch/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "../node_modules/.tmp/tsconfig.nightwatch.tsbuildinfo", + + "target": "ESNext", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": "../", + "lib": ["ESNext", "dom"], + "types": ["nightwatch"] + }, + "include": ["../node_modules/@nightwatch/**/*", "../src/components/**/*", "../tests/e2e/**/*"], + "ts-node": { + "transpileOnly": true + }, + "files": ["nightwatch.d.ts"] +} diff --git a/playground/typescript-pinia-nightwatch/package.json b/playground/typescript-pinia-nightwatch/package.json new file mode 100644 index 000000000..edc96c89e --- /dev/null +++ b/playground/typescript-pinia-nightwatch/package.json @@ -0,0 +1,36 @@ +{ + "name": "typescript-pinia-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "nightwatch tests/e2e/*", + "test:unit": "nightwatch src/**/__tests__/*", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "nightwatch": "^3.4.0", + "npm-run-all2": "^6.1.2", + "ts-node": "^10.9.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-pinia-nightwatch/public/favicon.ico b/playground/typescript-pinia-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-pinia-nightwatch/src/App.vue b/playground/typescript-pinia-nightwatch/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-pinia-nightwatch/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-pinia-nightwatch/src/assets/logo.svg b/playground/typescript-pinia-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-pinia-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-pinia-nightwatch/src/assets/main.css b/playground/typescript-pinia-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-pinia-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..810641e6e --- /dev/null +++ b/playground/typescript-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,14 @@ +describe('Hello World', function () { + before((browser) => { + browser.init() + }) + + it('renders properly', async function () { + const welcomeComponent = await browser.mountComponent('/src/components/HelloWorld.vue', {props: {msg: 'Hello Nightwatch'}}); + + browser.expect.element(welcomeComponent).to.be.present; + browser.expect.element('h1').text.to.contain('Hello Nightwatch'); + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-pinia-nightwatch/src/main.ts b/playground/typescript-pinia-nightwatch/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-pinia-nightwatch/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-pinia-nightwatch/src/stores/counter.ts b/playground/typescript-pinia-nightwatch/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-pinia-nightwatch/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-pinia-nightwatch/tests/e2e/example.ts b/playground/typescript-pinia-nightwatch/tests/e2e/example.ts new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/typescript-pinia-nightwatch/tests/e2e/example.ts @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-pinia-nightwatch/tsconfig.app.json b/playground/typescript-pinia-nightwatch/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-pinia-nightwatch/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-pinia-nightwatch/tsconfig.json b/playground/typescript-pinia-nightwatch/tsconfig.json new file mode 100644 index 000000000..5c385ae2c --- /dev/null +++ b/playground/typescript-pinia-nightwatch/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./nightwatch/tsconfig.json" + } + ] +} diff --git a/playground/typescript-pinia-nightwatch/tsconfig.node.json b/playground/typescript-pinia-nightwatch/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-pinia-nightwatch/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-pinia-nightwatch/vite.config.ts b/playground/typescript-pinia-nightwatch/vite.config.ts new file mode 100644 index 000000000..fd83c5b21 --- /dev/null +++ b/playground/typescript-pinia-nightwatch/vite.config.ts @@ -0,0 +1,20 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + nightwatchPlugin({ + renderPage: './nightwatch/index.html' + }), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-pinia-playwright/.gitignore b/playground/typescript-pinia-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/typescript-pinia-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/typescript-pinia-playwright/.vscode/extensions.json b/playground/typescript-pinia-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/typescript-pinia-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/typescript-pinia-playwright/README.md b/playground/typescript-pinia-playwright/README.md new file mode 100644 index 000000000..36afc2db8 --- /dev/null +++ b/playground/typescript-pinia-playwright/README.md @@ -0,0 +1,59 @@ +# typescript-pinia-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/typescript-pinia-playwright/e2e/tsconfig.json b/playground/typescript-pinia-playwright/e2e/tsconfig.json new file mode 100644 index 000000000..be3bbfc0e --- /dev/null +++ b/playground/typescript-pinia-playwright/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": ["./**/*"] +} diff --git a/playground/typescript-pinia-playwright/e2e/vue.spec.ts b/playground/typescript-pinia-playwright/e2e/vue.spec.ts new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/typescript-pinia-playwright/e2e/vue.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/typescript-pinia-playwright/env.d.ts b/playground/typescript-pinia-playwright/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-pinia-playwright/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-pinia-playwright/index.html b/playground/typescript-pinia-playwright/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-pinia-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-pinia-playwright/package.json b/playground/typescript-pinia-playwright/package.json new file mode 100644 index 000000000..a02715868 --- /dev/null +++ b/playground/typescript-pinia-playwright/package.json @@ -0,0 +1,29 @@ +{ + "name": "typescript-pinia-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "playwright test", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-pinia-playwright/playwright.config.ts b/playground/typescript-pinia-playwright/playwright.config.ts new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/typescript-pinia-playwright/playwright.config.ts @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/typescript-pinia-playwright/public/favicon.ico b/playground/typescript-pinia-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-pinia-playwright/src/App.vue b/playground/typescript-pinia-playwright/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-pinia-playwright/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-pinia-playwright/src/assets/logo.svg b/playground/typescript-pinia-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-pinia-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-pinia-playwright/src/assets/main.css b/playground/typescript-pinia-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-pinia-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-pinia-playwright/src/main.ts b/playground/typescript-pinia-playwright/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-pinia-playwright/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-pinia-playwright/src/stores/counter.ts b/playground/typescript-pinia-playwright/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-pinia-playwright/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-pinia-playwright/tsconfig.app.json b/playground/typescript-pinia-playwright/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-pinia-playwright/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-pinia-playwright/tsconfig.json b/playground/typescript-pinia-playwright/tsconfig.json new file mode 100644 index 000000000..66b5e5703 --- /dev/null +++ b/playground/typescript-pinia-playwright/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/playground/typescript-pinia-playwright/tsconfig.node.json b/playground/typescript-pinia-playwright/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-pinia-playwright/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-pinia-playwright/vite.config.ts b/playground/typescript-pinia-playwright/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-pinia-playwright/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-pinia-vitest-cypress/.gitignore b/playground/typescript-pinia-vitest-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-pinia-vitest-cypress/README.md b/playground/typescript-pinia-vitest-cypress/README.md new file mode 100644 index 000000000..0fede194f --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/README.md @@ -0,0 +1,62 @@ +# typescript-pinia-vitest-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-pinia-vitest-cypress/cypress.config.ts b/playground/typescript-pinia-vitest-cypress/cypress.config.ts new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/cypress.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/typescript-pinia-vitest-cypress/cypress/e2e/example.cy.ts b/playground/typescript-pinia-vitest-cypress/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-pinia-vitest-cypress/cypress/e2e/tsconfig.json b/playground/typescript-pinia-vitest-cypress/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-pinia-vitest-cypress/cypress/fixtures/example.json b/playground/typescript-pinia-vitest-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-pinia-vitest-cypress/cypress/support/commands.ts b/playground/typescript-pinia-vitest-cypress/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-pinia-vitest-cypress/cypress/support/e2e.ts b/playground/typescript-pinia-vitest-cypress/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-pinia-vitest-cypress/env.d.ts b/playground/typescript-pinia-vitest-cypress/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-pinia-vitest-cypress/index.html b/playground/typescript-pinia-vitest-cypress/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-pinia-vitest-cypress/package.json b/playground/typescript-pinia-vitest-cypress/package.json new file mode 100644 index 000000000..cd128b695 --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/package.json @@ -0,0 +1,36 @@ +{ + "name": "typescript-pinia-vitest-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-pinia-vitest-cypress/public/favicon.ico b/playground/typescript-pinia-vitest-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-pinia-vitest-cypress/src/App.vue b/playground/typescript-pinia-vitest-cypress/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-pinia-vitest-cypress/src/assets/logo.svg b/playground/typescript-pinia-vitest-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-pinia-vitest-cypress/src/assets/main.css b/playground/typescript-pinia-vitest-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-pinia-vitest-cypress/src/main.ts b/playground/typescript-pinia-vitest-cypress/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-pinia-vitest-cypress/src/stores/counter.ts b/playground/typescript-pinia-vitest-cypress/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-pinia-vitest-cypress/tsconfig.app.json b/playground/typescript-pinia-vitest-cypress/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-pinia-vitest-cypress/tsconfig.json b/playground/typescript-pinia-vitest-cypress/tsconfig.json new file mode 100644 index 000000000..5304731b8 --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-pinia-vitest-cypress/tsconfig.node.json b/playground/typescript-pinia-vitest-cypress/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-pinia-vitest-cypress/tsconfig.vitest.json b/playground/typescript-pinia-vitest-cypress/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-pinia-vitest-cypress/vite.config.ts b/playground/typescript-pinia-vitest-cypress/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-pinia-vitest-cypress/vitest.config.ts b/playground/typescript-pinia-vitest-cypress/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-pinia-vitest-cypress/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-pinia-vitest-nightwatch/.gitignore b/playground/typescript-pinia-vitest-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/typescript-pinia-vitest-nightwatch/.vscode/extensions.json b/playground/typescript-pinia-vitest-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/typescript-pinia-vitest-nightwatch/README.md b/playground/typescript-pinia-vitest-nightwatch/README.md new file mode 100644 index 000000000..70e40463e --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/README.md @@ -0,0 +1,69 @@ +# typescript-pinia-vitest-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/typescript-pinia-vitest-nightwatch/env.d.ts b/playground/typescript-pinia-vitest-nightwatch/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-pinia-vitest-nightwatch/index.html b/playground/typescript-pinia-vitest-nightwatch/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-pinia-vitest-nightwatch/nightwatch.conf.cjs b/playground/typescript-pinia-vitest-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/typescript-pinia-vitest-nightwatch/nightwatch/nightwatch.d.ts b/playground/typescript-pinia-vitest-nightwatch/nightwatch/nightwatch.d.ts new file mode 100644 index 000000000..616e63f9f --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/nightwatch/nightwatch.d.ts @@ -0,0 +1,13 @@ +import { NightwatchCustomAssertions, NightwatchCustomCommands } from 'nightwatch' + +declare module 'nightwatch' { + interface NightwatchCustomAssertions { + // Add your custom assertions' types here + // elementHasCount: (selector: string, count: number) => NightwatchBrowser + } + + interface NightwatchCustomCommands { + // Add your custom commands' types here + // strictClick: (selector: string) => NightwatchBrowser + } +} diff --git a/playground/typescript-pinia-vitest-nightwatch/nightwatch/tsconfig.json b/playground/typescript-pinia-vitest-nightwatch/nightwatch/tsconfig.json new file mode 100644 index 000000000..8cd7ca1da --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/nightwatch/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "../node_modules/.tmp/tsconfig.nightwatch.tsbuildinfo", + + "target": "ESNext", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": "../", + "lib": ["ESNext", "dom"], + "types": ["nightwatch"] + }, + "include": ["../node_modules/@nightwatch/**/*", "../src/components/**/*", "../tests/e2e/**/*"], + "ts-node": { + "transpileOnly": true + }, + "files": ["nightwatch.d.ts"] +} diff --git a/playground/typescript-pinia-vitest-nightwatch/package.json b/playground/typescript-pinia-vitest-nightwatch/package.json new file mode 100644 index 000000000..a4884aad2 --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/package.json @@ -0,0 +1,39 @@ +{ + "name": "typescript-pinia-vitest-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "nightwatch tests/e2e/*", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "jsdom": "^24.0.0", + "nightwatch": "^3.4.0", + "npm-run-all2": "^6.1.2", + "ts-node": "^10.9.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-pinia-vitest-nightwatch/public/favicon.ico b/playground/typescript-pinia-vitest-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-pinia-vitest-nightwatch/src/App.vue b/playground/typescript-pinia-vitest-nightwatch/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-pinia-vitest-nightwatch/src/assets/logo.svg b/playground/typescript-pinia-vitest-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-pinia-vitest-nightwatch/src/assets/main.css b/playground/typescript-pinia-vitest-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-pinia-vitest-nightwatch/src/main.ts b/playground/typescript-pinia-vitest-nightwatch/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-pinia-vitest-nightwatch/src/stores/counter.ts b/playground/typescript-pinia-vitest-nightwatch/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-pinia-vitest-nightwatch/tests/e2e/example.ts b/playground/typescript-pinia-vitest-nightwatch/tests/e2e/example.ts new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/tests/e2e/example.ts @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-pinia-vitest-nightwatch/tsconfig.app.json b/playground/typescript-pinia-vitest-nightwatch/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-pinia-vitest-nightwatch/tsconfig.json b/playground/typescript-pinia-vitest-nightwatch/tsconfig.json new file mode 100644 index 000000000..a5352e667 --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + }, + { + "path": "./nightwatch/tsconfig.json" + } + ] +} diff --git a/playground/typescript-pinia-vitest-nightwatch/tsconfig.node.json b/playground/typescript-pinia-vitest-nightwatch/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-pinia-vitest-nightwatch/tsconfig.vitest.json b/playground/typescript-pinia-vitest-nightwatch/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-pinia-vitest-nightwatch/vite.config.ts b/playground/typescript-pinia-vitest-nightwatch/vite.config.ts new file mode 100644 index 000000000..be3cb9c57 --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + nightwatchPlugin(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-pinia-vitest-nightwatch/vitest.config.ts b/playground/typescript-pinia-vitest-nightwatch/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-pinia-vitest-nightwatch/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-pinia-vitest-playwright/.gitignore b/playground/typescript-pinia-vitest-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/typescript-pinia-vitest-playwright/.vscode/extensions.json b/playground/typescript-pinia-vitest-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/typescript-pinia-vitest-playwright/README.md b/playground/typescript-pinia-vitest-playwright/README.md new file mode 100644 index 000000000..5d406ee51 --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/README.md @@ -0,0 +1,65 @@ +# typescript-pinia-vitest-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/typescript-pinia-vitest-playwright/e2e/tsconfig.json b/playground/typescript-pinia-vitest-playwright/e2e/tsconfig.json new file mode 100644 index 000000000..be3bbfc0e --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": ["./**/*"] +} diff --git a/playground/typescript-pinia-vitest-playwright/e2e/vue.spec.ts b/playground/typescript-pinia-vitest-playwright/e2e/vue.spec.ts new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/e2e/vue.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/typescript-pinia-vitest-playwright/env.d.ts b/playground/typescript-pinia-vitest-playwright/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-pinia-vitest-playwright/index.html b/playground/typescript-pinia-vitest-playwright/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-pinia-vitest-playwright/package.json b/playground/typescript-pinia-vitest-playwright/package.json new file mode 100644 index 000000000..2c67fd655 --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/package.json @@ -0,0 +1,34 @@ +{ + "name": "typescript-pinia-vitest-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "playwright test", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-pinia-vitest-playwright/playwright.config.ts b/playground/typescript-pinia-vitest-playwright/playwright.config.ts new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/playwright.config.ts @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/typescript-pinia-vitest-playwright/public/favicon.ico b/playground/typescript-pinia-vitest-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-pinia-vitest-playwright/src/App.vue b/playground/typescript-pinia-vitest-playwright/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-pinia-vitest-playwright/src/assets/logo.svg b/playground/typescript-pinia-vitest-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-pinia-vitest-playwright/src/assets/main.css b/playground/typescript-pinia-vitest-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-pinia-vitest-playwright/src/main.ts b/playground/typescript-pinia-vitest-playwright/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-pinia-vitest-playwright/src/stores/counter.ts b/playground/typescript-pinia-vitest-playwright/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-pinia-vitest-playwright/tsconfig.app.json b/playground/typescript-pinia-vitest-playwright/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-pinia-vitest-playwright/tsconfig.json b/playground/typescript-pinia-vitest-playwright/tsconfig.json new file mode 100644 index 000000000..100cf6a8f --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ] +} diff --git a/playground/typescript-pinia-vitest-playwright/tsconfig.node.json b/playground/typescript-pinia-vitest-playwright/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-pinia-vitest-playwright/tsconfig.vitest.json b/playground/typescript-pinia-vitest-playwright/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-pinia-vitest-playwright/vite.config.ts b/playground/typescript-pinia-vitest-playwright/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-pinia-vitest-playwright/vitest.config.ts b/playground/typescript-pinia-vitest-playwright/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-pinia-vitest-playwright/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-pinia-vitest/.gitignore b/playground/typescript-pinia-vitest/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-pinia-vitest/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-pinia-vitest/README.md b/playground/typescript-pinia-vitest/README.md new file mode 100644 index 000000000..fbe43309a --- /dev/null +++ b/playground/typescript-pinia-vitest/README.md @@ -0,0 +1,46 @@ +# typescript-pinia-vitest + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` diff --git a/playground/typescript-pinia-vitest/env.d.ts b/playground/typescript-pinia-vitest/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-pinia-vitest/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-pinia-vitest/index.html b/playground/typescript-pinia-vitest/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-pinia-vitest/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-pinia-vitest/package.json b/playground/typescript-pinia-vitest/package.json new file mode 100644 index 000000000..7cec5ff5a --- /dev/null +++ b/playground/typescript-pinia-vitest/package.json @@ -0,0 +1,32 @@ +{ + "name": "typescript-pinia-vitest", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-pinia-vitest/public/favicon.ico b/playground/typescript-pinia-vitest/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-pinia-vitest/src/App.vue b/playground/typescript-pinia-vitest/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-pinia-vitest/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-pinia-vitest/src/assets/logo.svg b/playground/typescript-pinia-vitest/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-pinia-vitest/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-pinia-vitest/src/assets/main.css b/playground/typescript-pinia-vitest/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-pinia-vitest/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-pinia-vitest/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-pinia-vitest/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-pinia-vitest/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-pinia-vitest/src/main.ts b/playground/typescript-pinia-vitest/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-pinia-vitest/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-pinia-vitest/src/stores/counter.ts b/playground/typescript-pinia-vitest/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-pinia-vitest/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-pinia-vitest/tsconfig.app.json b/playground/typescript-pinia-vitest/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-pinia-vitest/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-pinia-vitest/tsconfig.json b/playground/typescript-pinia-vitest/tsconfig.json new file mode 100644 index 000000000..100cf6a8f --- /dev/null +++ b/playground/typescript-pinia-vitest/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ] +} diff --git a/playground/typescript-pinia-vitest/tsconfig.node.json b/playground/typescript-pinia-vitest/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-pinia-vitest/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-pinia-vitest/tsconfig.vitest.json b/playground/typescript-pinia-vitest/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-pinia-vitest/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-pinia-vitest/vite.config.ts b/playground/typescript-pinia-vitest/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-pinia-vitest/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-pinia-vitest/vitest.config.ts b/playground/typescript-pinia-vitest/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-pinia-vitest/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-pinia-with-tests/.gitignore b/playground/typescript-pinia-with-tests/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-pinia-with-tests/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-pinia-with-tests/README.md b/playground/typescript-pinia-with-tests/README.md new file mode 100644 index 000000000..6dea2f95a --- /dev/null +++ b/playground/typescript-pinia-with-tests/README.md @@ -0,0 +1,62 @@ +# typescript-pinia-with-tests + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-pinia-with-tests/cypress.config.ts b/playground/typescript-pinia-with-tests/cypress.config.ts new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/typescript-pinia-with-tests/cypress.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/typescript-pinia-with-tests/cypress/e2e/example.cy.ts b/playground/typescript-pinia-with-tests/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-pinia-with-tests/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-pinia-with-tests/cypress/e2e/tsconfig.json b/playground/typescript-pinia-with-tests/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-pinia-with-tests/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-pinia-with-tests/cypress/fixtures/example.json b/playground/typescript-pinia-with-tests/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-pinia-with-tests/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-pinia-with-tests/cypress/support/commands.ts b/playground/typescript-pinia-with-tests/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-pinia-with-tests/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-pinia-with-tests/cypress/support/e2e.ts b/playground/typescript-pinia-with-tests/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-pinia-with-tests/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-pinia-with-tests/env.d.ts b/playground/typescript-pinia-with-tests/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-pinia-with-tests/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-pinia-with-tests/index.html b/playground/typescript-pinia-with-tests/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-pinia-with-tests/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-pinia-with-tests/package.json b/playground/typescript-pinia-with-tests/package.json new file mode 100644 index 000000000..13cab1ecd --- /dev/null +++ b/playground/typescript-pinia-with-tests/package.json @@ -0,0 +1,36 @@ +{ + "name": "typescript-pinia-with-tests", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-pinia-with-tests/public/favicon.ico b/playground/typescript-pinia-with-tests/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-pinia-with-tests/src/App.vue b/playground/typescript-pinia-with-tests/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-pinia-with-tests/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-pinia-with-tests/src/assets/logo.svg b/playground/typescript-pinia-with-tests/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-pinia-with-tests/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-pinia-with-tests/src/assets/main.css b/playground/typescript-pinia-with-tests/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-pinia-with-tests/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-pinia-with-tests/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-pinia-with-tests/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-pinia-with-tests/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-pinia-with-tests/src/main.ts b/playground/typescript-pinia-with-tests/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-pinia-with-tests/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-pinia-with-tests/src/stores/counter.ts b/playground/typescript-pinia-with-tests/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-pinia-with-tests/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-pinia-with-tests/tsconfig.app.json b/playground/typescript-pinia-with-tests/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-pinia-with-tests/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-pinia-with-tests/tsconfig.json b/playground/typescript-pinia-with-tests/tsconfig.json new file mode 100644 index 000000000..5304731b8 --- /dev/null +++ b/playground/typescript-pinia-with-tests/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-pinia-with-tests/tsconfig.node.json b/playground/typescript-pinia-with-tests/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-pinia-with-tests/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-pinia-with-tests/tsconfig.vitest.json b/playground/typescript-pinia-with-tests/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-pinia-with-tests/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-pinia-with-tests/vite.config.ts b/playground/typescript-pinia-with-tests/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-pinia-with-tests/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-pinia-with-tests/vitest.config.ts b/playground/typescript-pinia-with-tests/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-pinia-with-tests/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-pinia/.gitignore b/playground/typescript-pinia/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-pinia/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-pinia/README.md b/playground/typescript-pinia/README.md new file mode 100644 index 000000000..47428c441 --- /dev/null +++ b/playground/typescript-pinia/README.md @@ -0,0 +1,40 @@ +# typescript-pinia + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` diff --git a/playground/typescript-pinia/env.d.ts b/playground/typescript-pinia/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-pinia/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-pinia/index.html b/playground/typescript-pinia/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-pinia/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-pinia/package.json b/playground/typescript-pinia/package.json new file mode 100644 index 000000000..fcbd0f238 --- /dev/null +++ b/playground/typescript-pinia/package.json @@ -0,0 +1,27 @@ +{ + "name": "typescript-pinia", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-pinia/public/favicon.ico b/playground/typescript-pinia/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-pinia/src/App.vue b/playground/typescript-pinia/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-pinia/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-pinia/src/assets/logo.svg b/playground/typescript-pinia/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-pinia/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-pinia/src/assets/main.css b/playground/typescript-pinia/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-pinia/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-pinia/src/main.ts b/playground/typescript-pinia/src/main.ts new file mode 100644 index 000000000..48dad4313 --- /dev/null +++ b/playground/typescript-pinia/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' +import App from './App.vue' + +const app = createApp(App) + +app.use(createPinia()) + +app.mount('#app') diff --git a/playground/typescript-pinia/src/stores/counter.ts b/playground/typescript-pinia/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-pinia/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-pinia/tsconfig.app.json b/playground/typescript-pinia/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-pinia/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-pinia/tsconfig.json b/playground/typescript-pinia/tsconfig.json new file mode 100644 index 000000000..66b5e5703 --- /dev/null +++ b/playground/typescript-pinia/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/playground/typescript-pinia/tsconfig.node.json b/playground/typescript-pinia/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-pinia/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-pinia/vite.config.ts b/playground/typescript-pinia/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-pinia/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-playwright/.gitignore b/playground/typescript-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/typescript-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/typescript-playwright/.vscode/extensions.json b/playground/typescript-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/typescript-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/typescript-playwright/README.md b/playground/typescript-playwright/README.md new file mode 100644 index 000000000..501c14eef --- /dev/null +++ b/playground/typescript-playwright/README.md @@ -0,0 +1,59 @@ +# typescript-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/typescript-playwright/e2e/tsconfig.json b/playground/typescript-playwright/e2e/tsconfig.json new file mode 100644 index 000000000..be3bbfc0e --- /dev/null +++ b/playground/typescript-playwright/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": ["./**/*"] +} diff --git a/playground/typescript-playwright/e2e/vue.spec.ts b/playground/typescript-playwright/e2e/vue.spec.ts new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/typescript-playwright/e2e/vue.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/typescript-playwright/env.d.ts b/playground/typescript-playwright/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-playwright/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-playwright/index.html b/playground/typescript-playwright/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-playwright/package.json b/playground/typescript-playwright/package.json new file mode 100644 index 000000000..01f4b6c7f --- /dev/null +++ b/playground/typescript-playwright/package.json @@ -0,0 +1,28 @@ +{ + "name": "typescript-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "playwright test", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-playwright/playwright.config.ts b/playground/typescript-playwright/playwright.config.ts new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/typescript-playwright/playwright.config.ts @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/typescript-playwright/public/favicon.ico b/playground/typescript-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-playwright/src/App.vue b/playground/typescript-playwright/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-playwright/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-playwright/src/assets/logo.svg b/playground/typescript-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-playwright/src/assets/main.css b/playground/typescript-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-playwright/src/main.ts b/playground/typescript-playwright/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript-playwright/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript-playwright/tsconfig.app.json b/playground/typescript-playwright/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-playwright/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-playwright/tsconfig.json b/playground/typescript-playwright/tsconfig.json new file mode 100644 index 000000000..66b5e5703 --- /dev/null +++ b/playground/typescript-playwright/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/playground/typescript-playwright/tsconfig.node.json b/playground/typescript-playwright/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-playwright/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-playwright/vite.config.ts b/playground/typescript-playwright/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-playwright/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-cypress/.gitignore b/playground/typescript-router-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-router-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-router-cypress/README.md b/playground/typescript-router-cypress/README.md new file mode 100644 index 000000000..64a9a833c --- /dev/null +++ b/playground/typescript-router-cypress/README.md @@ -0,0 +1,62 @@ +# typescript-router-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Headed Component Tests with [Cypress Component Testing](https://on.cypress.io/component) + +```sh +pnpm test:unit:dev # or `pnpm test:unit` for headless testing +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-router-cypress/cypress.config.ts b/playground/typescript-router-cypress/cypress.config.ts new file mode 100644 index 000000000..c8fac1298 --- /dev/null +++ b/playground/typescript-router-cypress/cypress.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + }, + component: { + specPattern: 'src/**/__tests__/*.{cy,spec}.{js,ts,jsx,tsx}', + devServer: { + framework: 'vue', + bundler: 'vite' + } + } +}) diff --git a/playground/typescript-router-cypress/cypress/e2e/example.cy.ts b/playground/typescript-router-cypress/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-router-cypress/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-router-cypress/cypress/e2e/tsconfig.json b/playground/typescript-router-cypress/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-router-cypress/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-router-cypress/cypress/fixtures/example.json b/playground/typescript-router-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-router-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-router-cypress/cypress/support/commands.ts b/playground/typescript-router-cypress/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-router-cypress/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-router-cypress/cypress/support/component-index.html b/playground/typescript-router-cypress/cypress/support/component-index.html new file mode 100644 index 000000000..5f9622ae2 --- /dev/null +++ b/playground/typescript-router-cypress/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + Components App + + +
+ + diff --git a/playground/typescript-router-cypress/cypress/support/component.ts b/playground/typescript-router-cypress/cypress/support/component.ts new file mode 100644 index 000000000..04e4c352b --- /dev/null +++ b/playground/typescript-router-cypress/cypress/support/component.ts @@ -0,0 +1,43 @@ +// *********************************************************** +// This example support/component.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') + +// Import global styles +import '@/assets/main.css' + +import { mount } from 'cypress/vue' + +// Augment the Cypress namespace to include type definitions for +// your custom command. +// Alternatively, can be defined in cypress/support/component.d.ts +// with a at the top of your spec. +/* eslint-disable @typescript-eslint/no-namespace */ +declare global { + namespace Cypress { + interface Chainable { + mount: typeof mount + } + } +} + +Cypress.Commands.add('mount', mount) + +// Example use: +// cy.mount(MyComponent) diff --git a/playground/typescript-router-cypress/cypress/support/e2e.ts b/playground/typescript-router-cypress/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-router-cypress/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-router-cypress/env.d.ts b/playground/typescript-router-cypress/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router-cypress/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router-cypress/index.html b/playground/typescript-router-cypress/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router-cypress/package.json b/playground/typescript-router-cypress/package.json new file mode 100644 index 000000000..8dd0b0b05 --- /dev/null +++ b/playground/typescript-router-cypress/package.json @@ -0,0 +1,33 @@ +{ + "name": "typescript-router-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "test:unit": "cypress run --component", + "test:unit:dev": "cypress open --component", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router-cypress/public/favicon.ico b/playground/typescript-router-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router-cypress/src/App.vue b/playground/typescript-router-cypress/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router-cypress/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router-cypress/src/assets/logo.svg b/playground/typescript-router-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router-cypress/src/assets/main.css b/playground/typescript-router-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router-cypress/src/components/HelloWorld.vue b/playground/typescript-router-cypress/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router-cypress/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router-cypress/src/components/TheWelcome.vue b/playground/typescript-router-cypress/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router-cypress/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router-cypress/src/components/WelcomeItem.vue b/playground/typescript-router-cypress/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router-cypress/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router-cypress/src/components/__tests__/HelloWorld.cy.ts b/playground/typescript-router-cypress/src/components/__tests__/HelloWorld.cy.ts new file mode 100644 index 000000000..535a0e51c --- /dev/null +++ b/playground/typescript-router-cypress/src/components/__tests__/HelloWorld.cy.ts @@ -0,0 +1,12 @@ +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('playground', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + }) + + it('renders properly', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + cy.get('h1').should('contain', 'Hello Cypress') + }) +}) diff --git a/playground/typescript-router-cypress/src/components/icons/IconCommunity.vue b/playground/typescript-router-cypress/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router-cypress/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-cypress/src/components/icons/IconDocumentation.vue b/playground/typescript-router-cypress/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router-cypress/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-cypress/src/components/icons/IconEcosystem.vue b/playground/typescript-router-cypress/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router-cypress/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-cypress/src/components/icons/IconSupport.vue b/playground/typescript-router-cypress/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router-cypress/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-cypress/src/components/icons/IconTooling.vue b/playground/typescript-router-cypress/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router-cypress/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router-cypress/src/main.ts b/playground/typescript-router-cypress/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-router-cypress/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router-cypress/src/router/index.ts b/playground/typescript-router-cypress/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router-cypress/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router-cypress/src/views/AboutView.vue b/playground/typescript-router-cypress/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router-cypress/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router-cypress/src/views/HomeView.vue b/playground/typescript-router-cypress/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router-cypress/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router-cypress/tsconfig.app.json b/playground/typescript-router-cypress/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router-cypress/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router-cypress/tsconfig.cypress-ct.json b/playground/typescript-router-cypress/tsconfig.cypress-ct.json new file mode 100644 index 000000000..12833b275 --- /dev/null +++ b/playground/typescript-router-cypress/tsconfig.cypress-ct.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.app.json", + "include": [ + "env.d.ts", + "src/**/*", + "src/**/*.vue", + "cypress/support/component.*", + "cypress/support/commands.ts" + ], + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.cypress-ct.tsbuildinfo" + } +} diff --git a/playground/typescript-router-cypress/tsconfig.json b/playground/typescript-router-cypress/tsconfig.json new file mode 100644 index 000000000..d3b6c3172 --- /dev/null +++ b/playground/typescript-router-cypress/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.cypress-ct.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-router-cypress/tsconfig.node.json b/playground/typescript-router-cypress/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router-cypress/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router-cypress/vite.config.ts b/playground/typescript-router-cypress/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-router-cypress/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-nightwatch/.gitignore b/playground/typescript-router-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/typescript-router-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/typescript-router-nightwatch/.vscode/extensions.json b/playground/typescript-router-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/typescript-router-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/typescript-router-nightwatch/README.md b/playground/typescript-router-nightwatch/README.md new file mode 100644 index 000000000..66d837506 --- /dev/null +++ b/playground/typescript-router-nightwatch/README.md @@ -0,0 +1,63 @@ +# typescript-router-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/typescript-router-nightwatch/env.d.ts b/playground/typescript-router-nightwatch/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router-nightwatch/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router-nightwatch/index.html b/playground/typescript-router-nightwatch/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router-nightwatch/nightwatch.conf.cjs b/playground/typescript-router-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/typescript-router-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/typescript-router-nightwatch/nightwatch/index.html b/playground/typescript-router-nightwatch/nightwatch/index.html new file mode 100644 index 000000000..b7e1ec765 --- /dev/null +++ b/playground/typescript-router-nightwatch/nightwatch/index.html @@ -0,0 +1,16 @@ + + + + + + + + + Vue Renderer + + + +
+ + + diff --git a/playground/typescript-router-nightwatch/nightwatch/nightwatch.d.ts b/playground/typescript-router-nightwatch/nightwatch/nightwatch.d.ts new file mode 100644 index 000000000..616e63f9f --- /dev/null +++ b/playground/typescript-router-nightwatch/nightwatch/nightwatch.d.ts @@ -0,0 +1,13 @@ +import { NightwatchCustomAssertions, NightwatchCustomCommands } from 'nightwatch' + +declare module 'nightwatch' { + interface NightwatchCustomAssertions { + // Add your custom assertions' types here + // elementHasCount: (selector: string, count: number) => NightwatchBrowser + } + + interface NightwatchCustomCommands { + // Add your custom commands' types here + // strictClick: (selector: string) => NightwatchBrowser + } +} diff --git a/playground/typescript-router-nightwatch/nightwatch/tsconfig.json b/playground/typescript-router-nightwatch/nightwatch/tsconfig.json new file mode 100644 index 000000000..8cd7ca1da --- /dev/null +++ b/playground/typescript-router-nightwatch/nightwatch/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "../node_modules/.tmp/tsconfig.nightwatch.tsbuildinfo", + + "target": "ESNext", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": "../", + "lib": ["ESNext", "dom"], + "types": ["nightwatch"] + }, + "include": ["../node_modules/@nightwatch/**/*", "../src/components/**/*", "../tests/e2e/**/*"], + "ts-node": { + "transpileOnly": true + }, + "files": ["nightwatch.d.ts"] +} diff --git a/playground/typescript-router-nightwatch/package.json b/playground/typescript-router-nightwatch/package.json new file mode 100644 index 000000000..45687d007 --- /dev/null +++ b/playground/typescript-router-nightwatch/package.json @@ -0,0 +1,36 @@ +{ + "name": "typescript-router-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "nightwatch tests/e2e/*", + "test:unit": "nightwatch src/**/__tests__/*", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "nightwatch": "^3.4.0", + "npm-run-all2": "^6.1.2", + "ts-node": "^10.9.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router-nightwatch/public/favicon.ico b/playground/typescript-router-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router-nightwatch/src/App.vue b/playground/typescript-router-nightwatch/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router-nightwatch/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router-nightwatch/src/assets/logo.svg b/playground/typescript-router-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router-nightwatch/src/assets/main.css b/playground/typescript-router-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router-nightwatch/src/components/HelloWorld.vue b/playground/typescript-router-nightwatch/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router-nightwatch/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router-nightwatch/src/components/TheWelcome.vue b/playground/typescript-router-nightwatch/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router-nightwatch/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router-nightwatch/src/components/WelcomeItem.vue b/playground/typescript-router-nightwatch/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router-nightwatch/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router-nightwatch/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-router-nightwatch/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..810641e6e --- /dev/null +++ b/playground/typescript-router-nightwatch/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,14 @@ +describe('Hello World', function () { + before((browser) => { + browser.init() + }) + + it('renders properly', async function () { + const welcomeComponent = await browser.mountComponent('/src/components/HelloWorld.vue', {props: {msg: 'Hello Nightwatch'}}); + + browser.expect.element(welcomeComponent).to.be.present; + browser.expect.element('h1').text.to.contain('Hello Nightwatch'); + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-router-nightwatch/src/components/icons/IconCommunity.vue b/playground/typescript-router-nightwatch/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router-nightwatch/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-nightwatch/src/components/icons/IconDocumentation.vue b/playground/typescript-router-nightwatch/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router-nightwatch/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-nightwatch/src/components/icons/IconEcosystem.vue b/playground/typescript-router-nightwatch/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router-nightwatch/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-nightwatch/src/components/icons/IconSupport.vue b/playground/typescript-router-nightwatch/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router-nightwatch/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-nightwatch/src/components/icons/IconTooling.vue b/playground/typescript-router-nightwatch/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router-nightwatch/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router-nightwatch/src/main.ts b/playground/typescript-router-nightwatch/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-router-nightwatch/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router-nightwatch/src/router/index.ts b/playground/typescript-router-nightwatch/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router-nightwatch/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router-nightwatch/src/views/AboutView.vue b/playground/typescript-router-nightwatch/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router-nightwatch/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router-nightwatch/src/views/HomeView.vue b/playground/typescript-router-nightwatch/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router-nightwatch/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router-nightwatch/tests/e2e/example.ts b/playground/typescript-router-nightwatch/tests/e2e/example.ts new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/typescript-router-nightwatch/tests/e2e/example.ts @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-router-nightwatch/tsconfig.app.json b/playground/typescript-router-nightwatch/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router-nightwatch/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router-nightwatch/tsconfig.json b/playground/typescript-router-nightwatch/tsconfig.json new file mode 100644 index 000000000..5c385ae2c --- /dev/null +++ b/playground/typescript-router-nightwatch/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./nightwatch/tsconfig.json" + } + ] +} diff --git a/playground/typescript-router-nightwatch/tsconfig.node.json b/playground/typescript-router-nightwatch/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router-nightwatch/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router-nightwatch/vite.config.ts b/playground/typescript-router-nightwatch/vite.config.ts new file mode 100644 index 000000000..fd83c5b21 --- /dev/null +++ b/playground/typescript-router-nightwatch/vite.config.ts @@ -0,0 +1,20 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + nightwatchPlugin({ + renderPage: './nightwatch/index.html' + }), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-pinia-cypress/.gitignore b/playground/typescript-router-pinia-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-router-pinia-cypress/README.md b/playground/typescript-router-pinia-cypress/README.md new file mode 100644 index 000000000..5d2b74d4e --- /dev/null +++ b/playground/typescript-router-pinia-cypress/README.md @@ -0,0 +1,62 @@ +# typescript-router-pinia-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Headed Component Tests with [Cypress Component Testing](https://on.cypress.io/component) + +```sh +pnpm test:unit:dev # or `pnpm test:unit` for headless testing +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-router-pinia-cypress/cypress.config.ts b/playground/typescript-router-pinia-cypress/cypress.config.ts new file mode 100644 index 000000000..c8fac1298 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/cypress.config.ts @@ -0,0 +1,15 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + }, + component: { + specPattern: 'src/**/__tests__/*.{cy,spec}.{js,ts,jsx,tsx}', + devServer: { + framework: 'vue', + bundler: 'vite' + } + } +}) diff --git a/playground/typescript-router-pinia-cypress/cypress/e2e/example.cy.ts b/playground/typescript-router-pinia-cypress/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-router-pinia-cypress/cypress/e2e/tsconfig.json b/playground/typescript-router-pinia-cypress/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-router-pinia-cypress/cypress/fixtures/example.json b/playground/typescript-router-pinia-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-router-pinia-cypress/cypress/support/commands.ts b/playground/typescript-router-pinia-cypress/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-router-pinia-cypress/cypress/support/component-index.html b/playground/typescript-router-pinia-cypress/cypress/support/component-index.html new file mode 100644 index 000000000..5f9622ae2 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/cypress/support/component-index.html @@ -0,0 +1,12 @@ + + + + + + + Components App + + +
+ + diff --git a/playground/typescript-router-pinia-cypress/cypress/support/component.ts b/playground/typescript-router-pinia-cypress/cypress/support/component.ts new file mode 100644 index 000000000..04e4c352b --- /dev/null +++ b/playground/typescript-router-pinia-cypress/cypress/support/component.ts @@ -0,0 +1,43 @@ +// *********************************************************** +// This example support/component.ts is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') + +// Import global styles +import '@/assets/main.css' + +import { mount } from 'cypress/vue' + +// Augment the Cypress namespace to include type definitions for +// your custom command. +// Alternatively, can be defined in cypress/support/component.d.ts +// with a at the top of your spec. +/* eslint-disable @typescript-eslint/no-namespace */ +declare global { + namespace Cypress { + interface Chainable { + mount: typeof mount + } + } +} + +Cypress.Commands.add('mount', mount) + +// Example use: +// cy.mount(MyComponent) diff --git a/playground/typescript-router-pinia-cypress/cypress/support/e2e.ts b/playground/typescript-router-pinia-cypress/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-router-pinia-cypress/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-router-pinia-cypress/env.d.ts b/playground/typescript-router-pinia-cypress/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router-pinia-cypress/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router-pinia-cypress/index.html b/playground/typescript-router-pinia-cypress/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router-pinia-cypress/package.json b/playground/typescript-router-pinia-cypress/package.json new file mode 100644 index 000000000..ead9d1571 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/package.json @@ -0,0 +1,34 @@ +{ + "name": "typescript-router-pinia-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "test:unit": "cypress run --component", + "test:unit:dev": "cypress open --component", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router-pinia-cypress/public/favicon.ico b/playground/typescript-router-pinia-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router-pinia-cypress/src/App.vue b/playground/typescript-router-pinia-cypress/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router-pinia-cypress/src/assets/logo.svg b/playground/typescript-router-pinia-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router-pinia-cypress/src/assets/main.css b/playground/typescript-router-pinia-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router-pinia-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router-pinia-cypress/src/components/HelloWorld.vue b/playground/typescript-router-pinia-cypress/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router-pinia-cypress/src/components/TheWelcome.vue b/playground/typescript-router-pinia-cypress/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router-pinia-cypress/src/components/WelcomeItem.vue b/playground/typescript-router-pinia-cypress/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router-pinia-cypress/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router-pinia-cypress/src/components/__tests__/HelloWorld.cy.ts b/playground/typescript-router-pinia-cypress/src/components/__tests__/HelloWorld.cy.ts new file mode 100644 index 000000000..535a0e51c --- /dev/null +++ b/playground/typescript-router-pinia-cypress/src/components/__tests__/HelloWorld.cy.ts @@ -0,0 +1,12 @@ +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('playground', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + }) + + it('renders properly', () => { + cy.mount(HelloWorld, { props: { msg: 'Hello Cypress' } }) + cy.get('h1').should('contain', 'Hello Cypress') + }) +}) diff --git a/playground/typescript-router-pinia-cypress/src/components/icons/IconCommunity.vue b/playground/typescript-router-pinia-cypress/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-cypress/src/components/icons/IconDocumentation.vue b/playground/typescript-router-pinia-cypress/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router-pinia-cypress/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-cypress/src/components/icons/IconEcosystem.vue b/playground/typescript-router-pinia-cypress/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router-pinia-cypress/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-cypress/src/components/icons/IconSupport.vue b/playground/typescript-router-pinia-cypress/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-cypress/src/components/icons/IconTooling.vue b/playground/typescript-router-pinia-cypress/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router-pinia-cypress/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router-pinia-cypress/src/main.ts b/playground/typescript-router-pinia-cypress/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router-pinia-cypress/src/router/index.ts b/playground/typescript-router-pinia-cypress/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router-pinia-cypress/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router-pinia-cypress/src/stores/counter.ts b/playground/typescript-router-pinia-cypress/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-router-pinia-cypress/src/views/AboutView.vue b/playground/typescript-router-pinia-cypress/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router-pinia-cypress/src/views/HomeView.vue b/playground/typescript-router-pinia-cypress/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router-pinia-cypress/tsconfig.app.json b/playground/typescript-router-pinia-cypress/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router-pinia-cypress/tsconfig.cypress-ct.json b/playground/typescript-router-pinia-cypress/tsconfig.cypress-ct.json new file mode 100644 index 000000000..12833b275 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/tsconfig.cypress-ct.json @@ -0,0 +1,15 @@ +{ + "extends": "./tsconfig.app.json", + "include": [ + "env.d.ts", + "src/**/*", + "src/**/*.vue", + "cypress/support/component.*", + "cypress/support/commands.ts" + ], + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.cypress-ct.tsbuildinfo" + } +} diff --git a/playground/typescript-router-pinia-cypress/tsconfig.json b/playground/typescript-router-pinia-cypress/tsconfig.json new file mode 100644 index 000000000..d3b6c3172 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.cypress-ct.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-router-pinia-cypress/tsconfig.node.json b/playground/typescript-router-pinia-cypress/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router-pinia-cypress/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router-pinia-cypress/vite.config.ts b/playground/typescript-router-pinia-cypress/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-router-pinia-cypress/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-pinia-nightwatch/.gitignore b/playground/typescript-router-pinia-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/typescript-router-pinia-nightwatch/.vscode/extensions.json b/playground/typescript-router-pinia-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/typescript-router-pinia-nightwatch/README.md b/playground/typescript-router-pinia-nightwatch/README.md new file mode 100644 index 000000000..7b3a91698 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/README.md @@ -0,0 +1,63 @@ +# typescript-router-pinia-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/typescript-router-pinia-nightwatch/env.d.ts b/playground/typescript-router-pinia-nightwatch/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router-pinia-nightwatch/index.html b/playground/typescript-router-pinia-nightwatch/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router-pinia-nightwatch/nightwatch.conf.cjs b/playground/typescript-router-pinia-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/typescript-router-pinia-nightwatch/nightwatch/index.html b/playground/typescript-router-pinia-nightwatch/nightwatch/index.html new file mode 100644 index 000000000..b7e1ec765 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/nightwatch/index.html @@ -0,0 +1,16 @@ + + + + + + + + + Vue Renderer + + + +
+ + + diff --git a/playground/typescript-router-pinia-nightwatch/nightwatch/nightwatch.d.ts b/playground/typescript-router-pinia-nightwatch/nightwatch/nightwatch.d.ts new file mode 100644 index 000000000..616e63f9f --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/nightwatch/nightwatch.d.ts @@ -0,0 +1,13 @@ +import { NightwatchCustomAssertions, NightwatchCustomCommands } from 'nightwatch' + +declare module 'nightwatch' { + interface NightwatchCustomAssertions { + // Add your custom assertions' types here + // elementHasCount: (selector: string, count: number) => NightwatchBrowser + } + + interface NightwatchCustomCommands { + // Add your custom commands' types here + // strictClick: (selector: string) => NightwatchBrowser + } +} diff --git a/playground/typescript-router-pinia-nightwatch/nightwatch/tsconfig.json b/playground/typescript-router-pinia-nightwatch/nightwatch/tsconfig.json new file mode 100644 index 000000000..8cd7ca1da --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/nightwatch/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "../node_modules/.tmp/tsconfig.nightwatch.tsbuildinfo", + + "target": "ESNext", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": "../", + "lib": ["ESNext", "dom"], + "types": ["nightwatch"] + }, + "include": ["../node_modules/@nightwatch/**/*", "../src/components/**/*", "../tests/e2e/**/*"], + "ts-node": { + "transpileOnly": true + }, + "files": ["nightwatch.d.ts"] +} diff --git a/playground/typescript-router-pinia-nightwatch/package.json b/playground/typescript-router-pinia-nightwatch/package.json new file mode 100644 index 000000000..57a421cf7 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/package.json @@ -0,0 +1,37 @@ +{ + "name": "typescript-router-pinia-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "nightwatch tests/e2e/*", + "test:unit": "nightwatch src/**/__tests__/*", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "nightwatch": "^3.4.0", + "npm-run-all2": "^6.1.2", + "ts-node": "^10.9.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router-pinia-nightwatch/public/favicon.ico b/playground/typescript-router-pinia-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router-pinia-nightwatch/src/App.vue b/playground/typescript-router-pinia-nightwatch/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router-pinia-nightwatch/src/assets/logo.svg b/playground/typescript-router-pinia-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router-pinia-nightwatch/src/assets/main.css b/playground/typescript-router-pinia-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router-pinia-nightwatch/src/components/HelloWorld.vue b/playground/typescript-router-pinia-nightwatch/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router-pinia-nightwatch/src/components/TheWelcome.vue b/playground/typescript-router-pinia-nightwatch/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router-pinia-nightwatch/src/components/WelcomeItem.vue b/playground/typescript-router-pinia-nightwatch/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-router-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..810641e6e --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,14 @@ +describe('Hello World', function () { + before((browser) => { + browser.init() + }) + + it('renders properly', async function () { + const welcomeComponent = await browser.mountComponent('/src/components/HelloWorld.vue', {props: {msg: 'Hello Nightwatch'}}); + + browser.expect.element(welcomeComponent).to.be.present; + browser.expect.element('h1').text.to.contain('Hello Nightwatch'); + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-router-pinia-nightwatch/src/components/icons/IconCommunity.vue b/playground/typescript-router-pinia-nightwatch/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-nightwatch/src/components/icons/IconDocumentation.vue b/playground/typescript-router-pinia-nightwatch/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-nightwatch/src/components/icons/IconEcosystem.vue b/playground/typescript-router-pinia-nightwatch/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-nightwatch/src/components/icons/IconSupport.vue b/playground/typescript-router-pinia-nightwatch/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-nightwatch/src/components/icons/IconTooling.vue b/playground/typescript-router-pinia-nightwatch/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router-pinia-nightwatch/src/main.ts b/playground/typescript-router-pinia-nightwatch/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router-pinia-nightwatch/src/router/index.ts b/playground/typescript-router-pinia-nightwatch/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router-pinia-nightwatch/src/stores/counter.ts b/playground/typescript-router-pinia-nightwatch/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-router-pinia-nightwatch/src/views/AboutView.vue b/playground/typescript-router-pinia-nightwatch/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router-pinia-nightwatch/src/views/HomeView.vue b/playground/typescript-router-pinia-nightwatch/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router-pinia-nightwatch/tests/e2e/example.ts b/playground/typescript-router-pinia-nightwatch/tests/e2e/example.ts new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/tests/e2e/example.ts @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-router-pinia-nightwatch/tsconfig.app.json b/playground/typescript-router-pinia-nightwatch/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router-pinia-nightwatch/tsconfig.json b/playground/typescript-router-pinia-nightwatch/tsconfig.json new file mode 100644 index 000000000..5c385ae2c --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./nightwatch/tsconfig.json" + } + ] +} diff --git a/playground/typescript-router-pinia-nightwatch/tsconfig.node.json b/playground/typescript-router-pinia-nightwatch/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router-pinia-nightwatch/vite.config.ts b/playground/typescript-router-pinia-nightwatch/vite.config.ts new file mode 100644 index 000000000..fd83c5b21 --- /dev/null +++ b/playground/typescript-router-pinia-nightwatch/vite.config.ts @@ -0,0 +1,20 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + nightwatchPlugin({ + renderPage: './nightwatch/index.html' + }), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-pinia-playwright/.gitignore b/playground/typescript-router-pinia-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/typescript-router-pinia-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/typescript-router-pinia-playwright/.vscode/extensions.json b/playground/typescript-router-pinia-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/typescript-router-pinia-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/typescript-router-pinia-playwright/README.md b/playground/typescript-router-pinia-playwright/README.md new file mode 100644 index 000000000..4a15f9b39 --- /dev/null +++ b/playground/typescript-router-pinia-playwright/README.md @@ -0,0 +1,59 @@ +# typescript-router-pinia-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/typescript-router-pinia-playwright/e2e/tsconfig.json b/playground/typescript-router-pinia-playwright/e2e/tsconfig.json new file mode 100644 index 000000000..be3bbfc0e --- /dev/null +++ b/playground/typescript-router-pinia-playwright/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": ["./**/*"] +} diff --git a/playground/typescript-router-pinia-playwright/e2e/vue.spec.ts b/playground/typescript-router-pinia-playwright/e2e/vue.spec.ts new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/typescript-router-pinia-playwright/e2e/vue.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/typescript-router-pinia-playwright/env.d.ts b/playground/typescript-router-pinia-playwright/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router-pinia-playwright/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router-pinia-playwright/index.html b/playground/typescript-router-pinia-playwright/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router-pinia-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router-pinia-playwright/package.json b/playground/typescript-router-pinia-playwright/package.json new file mode 100644 index 000000000..f4cd46239 --- /dev/null +++ b/playground/typescript-router-pinia-playwright/package.json @@ -0,0 +1,30 @@ +{ + "name": "typescript-router-pinia-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "playwright test", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router-pinia-playwright/playwright.config.ts b/playground/typescript-router-pinia-playwright/playwright.config.ts new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/typescript-router-pinia-playwright/playwright.config.ts @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/typescript-router-pinia-playwright/public/favicon.ico b/playground/typescript-router-pinia-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router-pinia-playwright/src/App.vue b/playground/typescript-router-pinia-playwright/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router-pinia-playwright/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router-pinia-playwright/src/assets/logo.svg b/playground/typescript-router-pinia-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router-pinia-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router-pinia-playwright/src/assets/main.css b/playground/typescript-router-pinia-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router-pinia-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router-pinia-playwright/src/components/HelloWorld.vue b/playground/typescript-router-pinia-playwright/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router-pinia-playwright/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router-pinia-playwright/src/components/TheWelcome.vue b/playground/typescript-router-pinia-playwright/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router-pinia-playwright/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router-pinia-playwright/src/components/WelcomeItem.vue b/playground/typescript-router-pinia-playwright/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router-pinia-playwright/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router-pinia-playwright/src/components/icons/IconCommunity.vue b/playground/typescript-router-pinia-playwright/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router-pinia-playwright/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-playwright/src/components/icons/IconDocumentation.vue b/playground/typescript-router-pinia-playwright/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router-pinia-playwright/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-playwright/src/components/icons/IconEcosystem.vue b/playground/typescript-router-pinia-playwright/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router-pinia-playwright/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-playwright/src/components/icons/IconSupport.vue b/playground/typescript-router-pinia-playwright/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router-pinia-playwright/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-playwright/src/components/icons/IconTooling.vue b/playground/typescript-router-pinia-playwright/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router-pinia-playwright/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router-pinia-playwright/src/main.ts b/playground/typescript-router-pinia-playwright/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-router-pinia-playwright/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router-pinia-playwright/src/router/index.ts b/playground/typescript-router-pinia-playwright/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router-pinia-playwright/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router-pinia-playwright/src/stores/counter.ts b/playground/typescript-router-pinia-playwright/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-router-pinia-playwright/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-router-pinia-playwright/src/views/AboutView.vue b/playground/typescript-router-pinia-playwright/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router-pinia-playwright/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router-pinia-playwright/src/views/HomeView.vue b/playground/typescript-router-pinia-playwright/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router-pinia-playwright/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router-pinia-playwright/tsconfig.app.json b/playground/typescript-router-pinia-playwright/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router-pinia-playwright/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router-pinia-playwright/tsconfig.json b/playground/typescript-router-pinia-playwright/tsconfig.json new file mode 100644 index 000000000..66b5e5703 --- /dev/null +++ b/playground/typescript-router-pinia-playwright/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/playground/typescript-router-pinia-playwright/tsconfig.node.json b/playground/typescript-router-pinia-playwright/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router-pinia-playwright/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router-pinia-playwright/vite.config.ts b/playground/typescript-router-pinia-playwright/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-router-pinia-playwright/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-pinia-vitest-cypress/.gitignore b/playground/typescript-router-pinia-vitest-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-router-pinia-vitest-cypress/README.md b/playground/typescript-router-pinia-vitest-cypress/README.md new file mode 100644 index 000000000..462f5441e --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/README.md @@ -0,0 +1,62 @@ +# typescript-router-pinia-vitest-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-router-pinia-vitest-cypress/cypress.config.ts b/playground/typescript-router-pinia-vitest-cypress/cypress.config.ts new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/cypress.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/typescript-router-pinia-vitest-cypress/cypress/e2e/example.cy.ts b/playground/typescript-router-pinia-vitest-cypress/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-router-pinia-vitest-cypress/cypress/e2e/tsconfig.json b/playground/typescript-router-pinia-vitest-cypress/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-router-pinia-vitest-cypress/cypress/fixtures/example.json b/playground/typescript-router-pinia-vitest-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-router-pinia-vitest-cypress/cypress/support/commands.ts b/playground/typescript-router-pinia-vitest-cypress/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-router-pinia-vitest-cypress/cypress/support/e2e.ts b/playground/typescript-router-pinia-vitest-cypress/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-router-pinia-vitest-cypress/env.d.ts b/playground/typescript-router-pinia-vitest-cypress/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router-pinia-vitest-cypress/index.html b/playground/typescript-router-pinia-vitest-cypress/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router-pinia-vitest-cypress/package.json b/playground/typescript-router-pinia-vitest-cypress/package.json new file mode 100644 index 000000000..bc7a06fc4 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/package.json @@ -0,0 +1,37 @@ +{ + "name": "typescript-router-pinia-vitest-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router-pinia-vitest-cypress/public/favicon.ico b/playground/typescript-router-pinia-vitest-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router-pinia-vitest-cypress/src/App.vue b/playground/typescript-router-pinia-vitest-cypress/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router-pinia-vitest-cypress/src/assets/logo.svg b/playground/typescript-router-pinia-vitest-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router-pinia-vitest-cypress/src/assets/main.css b/playground/typescript-router-pinia-vitest-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router-pinia-vitest-cypress/src/components/HelloWorld.vue b/playground/typescript-router-pinia-vitest-cypress/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router-pinia-vitest-cypress/src/components/TheWelcome.vue b/playground/typescript-router-pinia-vitest-cypress/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router-pinia-vitest-cypress/src/components/WelcomeItem.vue b/playground/typescript-router-pinia-vitest-cypress/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-router-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconCommunity.vue b/playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconDocumentation.vue b/playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconEcosystem.vue b/playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconSupport.vue b/playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconTooling.vue b/playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router-pinia-vitest-cypress/src/main.ts b/playground/typescript-router-pinia-vitest-cypress/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router-pinia-vitest-cypress/src/router/index.ts b/playground/typescript-router-pinia-vitest-cypress/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router-pinia-vitest-cypress/src/stores/counter.ts b/playground/typescript-router-pinia-vitest-cypress/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-router-pinia-vitest-cypress/src/views/AboutView.vue b/playground/typescript-router-pinia-vitest-cypress/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router-pinia-vitest-cypress/src/views/HomeView.vue b/playground/typescript-router-pinia-vitest-cypress/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router-pinia-vitest-cypress/tsconfig.app.json b/playground/typescript-router-pinia-vitest-cypress/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router-pinia-vitest-cypress/tsconfig.json b/playground/typescript-router-pinia-vitest-cypress/tsconfig.json new file mode 100644 index 000000000..5304731b8 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-router-pinia-vitest-cypress/tsconfig.node.json b/playground/typescript-router-pinia-vitest-cypress/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router-pinia-vitest-cypress/tsconfig.vitest.json b/playground/typescript-router-pinia-vitest-cypress/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-router-pinia-vitest-cypress/vite.config.ts b/playground/typescript-router-pinia-vitest-cypress/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-pinia-vitest-cypress/vitest.config.ts b/playground/typescript-router-pinia-vitest-cypress/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-cypress/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-router-pinia-vitest-nightwatch/.gitignore b/playground/typescript-router-pinia-vitest-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/typescript-router-pinia-vitest-nightwatch/.vscode/extensions.json b/playground/typescript-router-pinia-vitest-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/typescript-router-pinia-vitest-nightwatch/README.md b/playground/typescript-router-pinia-vitest-nightwatch/README.md new file mode 100644 index 000000000..60ac018ef --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/README.md @@ -0,0 +1,69 @@ +# typescript-router-pinia-vitest-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/typescript-router-pinia-vitest-nightwatch/env.d.ts b/playground/typescript-router-pinia-vitest-nightwatch/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router-pinia-vitest-nightwatch/index.html b/playground/typescript-router-pinia-vitest-nightwatch/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router-pinia-vitest-nightwatch/nightwatch.conf.cjs b/playground/typescript-router-pinia-vitest-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/typescript-router-pinia-vitest-nightwatch/nightwatch/nightwatch.d.ts b/playground/typescript-router-pinia-vitest-nightwatch/nightwatch/nightwatch.d.ts new file mode 100644 index 000000000..616e63f9f --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/nightwatch/nightwatch.d.ts @@ -0,0 +1,13 @@ +import { NightwatchCustomAssertions, NightwatchCustomCommands } from 'nightwatch' + +declare module 'nightwatch' { + interface NightwatchCustomAssertions { + // Add your custom assertions' types here + // elementHasCount: (selector: string, count: number) => NightwatchBrowser + } + + interface NightwatchCustomCommands { + // Add your custom commands' types here + // strictClick: (selector: string) => NightwatchBrowser + } +} diff --git a/playground/typescript-router-pinia-vitest-nightwatch/nightwatch/tsconfig.json b/playground/typescript-router-pinia-vitest-nightwatch/nightwatch/tsconfig.json new file mode 100644 index 000000000..8cd7ca1da --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/nightwatch/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "../node_modules/.tmp/tsconfig.nightwatch.tsbuildinfo", + + "target": "ESNext", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": "../", + "lib": ["ESNext", "dom"], + "types": ["nightwatch"] + }, + "include": ["../node_modules/@nightwatch/**/*", "../src/components/**/*", "../tests/e2e/**/*"], + "ts-node": { + "transpileOnly": true + }, + "files": ["nightwatch.d.ts"] +} diff --git a/playground/typescript-router-pinia-vitest-nightwatch/package.json b/playground/typescript-router-pinia-vitest-nightwatch/package.json new file mode 100644 index 000000000..e89dd3757 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/package.json @@ -0,0 +1,40 @@ +{ + "name": "typescript-router-pinia-vitest-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "nightwatch tests/e2e/*", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "jsdom": "^24.0.0", + "nightwatch": "^3.4.0", + "npm-run-all2": "^6.1.2", + "ts-node": "^10.9.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router-pinia-vitest-nightwatch/public/favicon.ico b/playground/typescript-router-pinia-vitest-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router-pinia-vitest-nightwatch/src/App.vue b/playground/typescript-router-pinia-vitest-nightwatch/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router-pinia-vitest-nightwatch/src/assets/logo.svg b/playground/typescript-router-pinia-vitest-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router-pinia-vitest-nightwatch/src/assets/main.css b/playground/typescript-router-pinia-vitest-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router-pinia-vitest-nightwatch/src/components/HelloWorld.vue b/playground/typescript-router-pinia-vitest-nightwatch/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router-pinia-vitest-nightwatch/src/components/TheWelcome.vue b/playground/typescript-router-pinia-vitest-nightwatch/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router-pinia-vitest-nightwatch/src/components/WelcomeItem.vue b/playground/typescript-router-pinia-vitest-nightwatch/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-router-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconCommunity.vue b/playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconDocumentation.vue b/playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconEcosystem.vue b/playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconSupport.vue b/playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconTooling.vue b/playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router-pinia-vitest-nightwatch/src/main.ts b/playground/typescript-router-pinia-vitest-nightwatch/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router-pinia-vitest-nightwatch/src/router/index.ts b/playground/typescript-router-pinia-vitest-nightwatch/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router-pinia-vitest-nightwatch/src/stores/counter.ts b/playground/typescript-router-pinia-vitest-nightwatch/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-router-pinia-vitest-nightwatch/src/views/AboutView.vue b/playground/typescript-router-pinia-vitest-nightwatch/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router-pinia-vitest-nightwatch/src/views/HomeView.vue b/playground/typescript-router-pinia-vitest-nightwatch/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router-pinia-vitest-nightwatch/tests/e2e/example.ts b/playground/typescript-router-pinia-vitest-nightwatch/tests/e2e/example.ts new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/tests/e2e/example.ts @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-router-pinia-vitest-nightwatch/tsconfig.app.json b/playground/typescript-router-pinia-vitest-nightwatch/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router-pinia-vitest-nightwatch/tsconfig.json b/playground/typescript-router-pinia-vitest-nightwatch/tsconfig.json new file mode 100644 index 000000000..a5352e667 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + }, + { + "path": "./nightwatch/tsconfig.json" + } + ] +} diff --git a/playground/typescript-router-pinia-vitest-nightwatch/tsconfig.node.json b/playground/typescript-router-pinia-vitest-nightwatch/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router-pinia-vitest-nightwatch/tsconfig.vitest.json b/playground/typescript-router-pinia-vitest-nightwatch/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-router-pinia-vitest-nightwatch/vite.config.ts b/playground/typescript-router-pinia-vitest-nightwatch/vite.config.ts new file mode 100644 index 000000000..be3cb9c57 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + nightwatchPlugin(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-pinia-vitest-nightwatch/vitest.config.ts b/playground/typescript-router-pinia-vitest-nightwatch/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-nightwatch/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-router-pinia-vitest-playwright/.gitignore b/playground/typescript-router-pinia-vitest-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/typescript-router-pinia-vitest-playwright/.vscode/extensions.json b/playground/typescript-router-pinia-vitest-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/typescript-router-pinia-vitest-playwright/README.md b/playground/typescript-router-pinia-vitest-playwright/README.md new file mode 100644 index 000000000..cdff825bf --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/README.md @@ -0,0 +1,65 @@ +# typescript-router-pinia-vitest-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/typescript-router-pinia-vitest-playwright/e2e/tsconfig.json b/playground/typescript-router-pinia-vitest-playwright/e2e/tsconfig.json new file mode 100644 index 000000000..be3bbfc0e --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": ["./**/*"] +} diff --git a/playground/typescript-router-pinia-vitest-playwright/e2e/vue.spec.ts b/playground/typescript-router-pinia-vitest-playwright/e2e/vue.spec.ts new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/e2e/vue.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/typescript-router-pinia-vitest-playwright/env.d.ts b/playground/typescript-router-pinia-vitest-playwright/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router-pinia-vitest-playwright/index.html b/playground/typescript-router-pinia-vitest-playwright/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router-pinia-vitest-playwright/package.json b/playground/typescript-router-pinia-vitest-playwright/package.json new file mode 100644 index 000000000..5e4379b7a --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/package.json @@ -0,0 +1,35 @@ +{ + "name": "typescript-router-pinia-vitest-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "playwright test", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router-pinia-vitest-playwright/playwright.config.ts b/playground/typescript-router-pinia-vitest-playwright/playwright.config.ts new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/playwright.config.ts @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/typescript-router-pinia-vitest-playwright/public/favicon.ico b/playground/typescript-router-pinia-vitest-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router-pinia-vitest-playwright/src/App.vue b/playground/typescript-router-pinia-vitest-playwright/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router-pinia-vitest-playwright/src/assets/logo.svg b/playground/typescript-router-pinia-vitest-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router-pinia-vitest-playwright/src/assets/main.css b/playground/typescript-router-pinia-vitest-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router-pinia-vitest-playwright/src/components/HelloWorld.vue b/playground/typescript-router-pinia-vitest-playwright/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router-pinia-vitest-playwright/src/components/TheWelcome.vue b/playground/typescript-router-pinia-vitest-playwright/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router-pinia-vitest-playwright/src/components/WelcomeItem.vue b/playground/typescript-router-pinia-vitest-playwright/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-router-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconCommunity.vue b/playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconDocumentation.vue b/playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconEcosystem.vue b/playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconSupport.vue b/playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconTooling.vue b/playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router-pinia-vitest-playwright/src/main.ts b/playground/typescript-router-pinia-vitest-playwright/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router-pinia-vitest-playwright/src/router/index.ts b/playground/typescript-router-pinia-vitest-playwright/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router-pinia-vitest-playwright/src/stores/counter.ts b/playground/typescript-router-pinia-vitest-playwright/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-router-pinia-vitest-playwright/src/views/AboutView.vue b/playground/typescript-router-pinia-vitest-playwright/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router-pinia-vitest-playwright/src/views/HomeView.vue b/playground/typescript-router-pinia-vitest-playwright/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router-pinia-vitest-playwright/tsconfig.app.json b/playground/typescript-router-pinia-vitest-playwright/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router-pinia-vitest-playwright/tsconfig.json b/playground/typescript-router-pinia-vitest-playwright/tsconfig.json new file mode 100644 index 000000000..100cf6a8f --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ] +} diff --git a/playground/typescript-router-pinia-vitest-playwright/tsconfig.node.json b/playground/typescript-router-pinia-vitest-playwright/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router-pinia-vitest-playwright/tsconfig.vitest.json b/playground/typescript-router-pinia-vitest-playwright/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-router-pinia-vitest-playwright/vite.config.ts b/playground/typescript-router-pinia-vitest-playwright/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-pinia-vitest-playwright/vitest.config.ts b/playground/typescript-router-pinia-vitest-playwright/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-router-pinia-vitest-playwright/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-router-pinia-vitest/.gitignore b/playground/typescript-router-pinia-vitest/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-router-pinia-vitest/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-router-pinia-vitest/README.md b/playground/typescript-router-pinia-vitest/README.md new file mode 100644 index 000000000..5277cebfc --- /dev/null +++ b/playground/typescript-router-pinia-vitest/README.md @@ -0,0 +1,46 @@ +# typescript-router-pinia-vitest + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` diff --git a/playground/typescript-router-pinia-vitest/env.d.ts b/playground/typescript-router-pinia-vitest/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router-pinia-vitest/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router-pinia-vitest/index.html b/playground/typescript-router-pinia-vitest/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router-pinia-vitest/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router-pinia-vitest/package.json b/playground/typescript-router-pinia-vitest/package.json new file mode 100644 index 000000000..691b6653f --- /dev/null +++ b/playground/typescript-router-pinia-vitest/package.json @@ -0,0 +1,33 @@ +{ + "name": "typescript-router-pinia-vitest", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router-pinia-vitest/public/favicon.ico b/playground/typescript-router-pinia-vitest/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router-pinia-vitest/src/App.vue b/playground/typescript-router-pinia-vitest/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router-pinia-vitest/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router-pinia-vitest/src/assets/logo.svg b/playground/typescript-router-pinia-vitest/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router-pinia-vitest/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router-pinia-vitest/src/assets/main.css b/playground/typescript-router-pinia-vitest/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router-pinia-vitest/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router-pinia-vitest/src/components/HelloWorld.vue b/playground/typescript-router-pinia-vitest/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router-pinia-vitest/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router-pinia-vitest/src/components/TheWelcome.vue b/playground/typescript-router-pinia-vitest/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router-pinia-vitest/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router-pinia-vitest/src/components/WelcomeItem.vue b/playground/typescript-router-pinia-vitest/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router-pinia-vitest/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router-pinia-vitest/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-router-pinia-vitest/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-router-pinia-vitest/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-router-pinia-vitest/src/components/icons/IconCommunity.vue b/playground/typescript-router-pinia-vitest/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router-pinia-vitest/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-vitest/src/components/icons/IconDocumentation.vue b/playground/typescript-router-pinia-vitest/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router-pinia-vitest/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-vitest/src/components/icons/IconEcosystem.vue b/playground/typescript-router-pinia-vitest/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router-pinia-vitest/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-vitest/src/components/icons/IconSupport.vue b/playground/typescript-router-pinia-vitest/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router-pinia-vitest/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-vitest/src/components/icons/IconTooling.vue b/playground/typescript-router-pinia-vitest/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router-pinia-vitest/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router-pinia-vitest/src/main.ts b/playground/typescript-router-pinia-vitest/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-router-pinia-vitest/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router-pinia-vitest/src/router/index.ts b/playground/typescript-router-pinia-vitest/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router-pinia-vitest/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router-pinia-vitest/src/stores/counter.ts b/playground/typescript-router-pinia-vitest/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-router-pinia-vitest/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-router-pinia-vitest/src/views/AboutView.vue b/playground/typescript-router-pinia-vitest/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router-pinia-vitest/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router-pinia-vitest/src/views/HomeView.vue b/playground/typescript-router-pinia-vitest/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router-pinia-vitest/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router-pinia-vitest/tsconfig.app.json b/playground/typescript-router-pinia-vitest/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router-pinia-vitest/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router-pinia-vitest/tsconfig.json b/playground/typescript-router-pinia-vitest/tsconfig.json new file mode 100644 index 000000000..100cf6a8f --- /dev/null +++ b/playground/typescript-router-pinia-vitest/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ] +} diff --git a/playground/typescript-router-pinia-vitest/tsconfig.node.json b/playground/typescript-router-pinia-vitest/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router-pinia-vitest/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router-pinia-vitest/tsconfig.vitest.json b/playground/typescript-router-pinia-vitest/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-router-pinia-vitest/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-router-pinia-vitest/vite.config.ts b/playground/typescript-router-pinia-vitest/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-router-pinia-vitest/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-pinia-vitest/vitest.config.ts b/playground/typescript-router-pinia-vitest/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-router-pinia-vitest/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-router-pinia-with-tests/.gitignore b/playground/typescript-router-pinia-with-tests/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-router-pinia-with-tests/README.md b/playground/typescript-router-pinia-with-tests/README.md new file mode 100644 index 000000000..b664aa57a --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/README.md @@ -0,0 +1,62 @@ +# typescript-router-pinia-with-tests + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-router-pinia-with-tests/cypress.config.ts b/playground/typescript-router-pinia-with-tests/cypress.config.ts new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/cypress.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/typescript-router-pinia-with-tests/cypress/e2e/example.cy.ts b/playground/typescript-router-pinia-with-tests/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-router-pinia-with-tests/cypress/e2e/tsconfig.json b/playground/typescript-router-pinia-with-tests/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-router-pinia-with-tests/cypress/fixtures/example.json b/playground/typescript-router-pinia-with-tests/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-router-pinia-with-tests/cypress/support/commands.ts b/playground/typescript-router-pinia-with-tests/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-router-pinia-with-tests/cypress/support/e2e.ts b/playground/typescript-router-pinia-with-tests/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-router-pinia-with-tests/env.d.ts b/playground/typescript-router-pinia-with-tests/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router-pinia-with-tests/index.html b/playground/typescript-router-pinia-with-tests/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router-pinia-with-tests/package.json b/playground/typescript-router-pinia-with-tests/package.json new file mode 100644 index 000000000..0d7334fc2 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/package.json @@ -0,0 +1,37 @@ +{ + "name": "typescript-router-pinia-with-tests", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router-pinia-with-tests/public/favicon.ico b/playground/typescript-router-pinia-with-tests/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router-pinia-with-tests/src/App.vue b/playground/typescript-router-pinia-with-tests/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router-pinia-with-tests/src/assets/logo.svg b/playground/typescript-router-pinia-with-tests/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router-pinia-with-tests/src/assets/main.css b/playground/typescript-router-pinia-with-tests/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router-pinia-with-tests/src/components/HelloWorld.vue b/playground/typescript-router-pinia-with-tests/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router-pinia-with-tests/src/components/TheWelcome.vue b/playground/typescript-router-pinia-with-tests/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router-pinia-with-tests/src/components/WelcomeItem.vue b/playground/typescript-router-pinia-with-tests/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router-pinia-with-tests/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-router-pinia-with-tests/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-router-pinia-with-tests/src/components/icons/IconCommunity.vue b/playground/typescript-router-pinia-with-tests/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-with-tests/src/components/icons/IconDocumentation.vue b/playground/typescript-router-pinia-with-tests/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-with-tests/src/components/icons/IconEcosystem.vue b/playground/typescript-router-pinia-with-tests/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-with-tests/src/components/icons/IconSupport.vue b/playground/typescript-router-pinia-with-tests/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia-with-tests/src/components/icons/IconTooling.vue b/playground/typescript-router-pinia-with-tests/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router-pinia-with-tests/src/main.ts b/playground/typescript-router-pinia-with-tests/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router-pinia-with-tests/src/router/index.ts b/playground/typescript-router-pinia-with-tests/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router-pinia-with-tests/src/stores/counter.ts b/playground/typescript-router-pinia-with-tests/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-router-pinia-with-tests/src/views/AboutView.vue b/playground/typescript-router-pinia-with-tests/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router-pinia-with-tests/src/views/HomeView.vue b/playground/typescript-router-pinia-with-tests/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router-pinia-with-tests/tsconfig.app.json b/playground/typescript-router-pinia-with-tests/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router-pinia-with-tests/tsconfig.json b/playground/typescript-router-pinia-with-tests/tsconfig.json new file mode 100644 index 000000000..5304731b8 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-router-pinia-with-tests/tsconfig.node.json b/playground/typescript-router-pinia-with-tests/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router-pinia-with-tests/tsconfig.vitest.json b/playground/typescript-router-pinia-with-tests/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-router-pinia-with-tests/vite.config.ts b/playground/typescript-router-pinia-with-tests/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-pinia-with-tests/vitest.config.ts b/playground/typescript-router-pinia-with-tests/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-router-pinia-with-tests/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-router-pinia/.gitignore b/playground/typescript-router-pinia/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-router-pinia/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-router-pinia/README.md b/playground/typescript-router-pinia/README.md new file mode 100644 index 000000000..4f731fff7 --- /dev/null +++ b/playground/typescript-router-pinia/README.md @@ -0,0 +1,40 @@ +# typescript-router-pinia + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` diff --git a/playground/typescript-router-pinia/env.d.ts b/playground/typescript-router-pinia/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router-pinia/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router-pinia/index.html b/playground/typescript-router-pinia/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router-pinia/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router-pinia/package.json b/playground/typescript-router-pinia/package.json new file mode 100644 index 000000000..6f6b50a76 --- /dev/null +++ b/playground/typescript-router-pinia/package.json @@ -0,0 +1,28 @@ +{ + "name": "typescript-router-pinia", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "pinia": "^2.1.7", + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router-pinia/public/favicon.ico b/playground/typescript-router-pinia/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router-pinia/src/App.vue b/playground/typescript-router-pinia/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router-pinia/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router-pinia/src/assets/logo.svg b/playground/typescript-router-pinia/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router-pinia/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router-pinia/src/assets/main.css b/playground/typescript-router-pinia/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router-pinia/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router-pinia/src/components/HelloWorld.vue b/playground/typescript-router-pinia/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router-pinia/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router-pinia/src/components/TheWelcome.vue b/playground/typescript-router-pinia/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router-pinia/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router-pinia/src/components/WelcomeItem.vue b/playground/typescript-router-pinia/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router-pinia/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router-pinia/src/components/icons/IconCommunity.vue b/playground/typescript-router-pinia/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router-pinia/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia/src/components/icons/IconDocumentation.vue b/playground/typescript-router-pinia/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router-pinia/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia/src/components/icons/IconEcosystem.vue b/playground/typescript-router-pinia/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router-pinia/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia/src/components/icons/IconSupport.vue b/playground/typescript-router-pinia/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router-pinia/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-pinia/src/components/icons/IconTooling.vue b/playground/typescript-router-pinia/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router-pinia/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router-pinia/src/main.ts b/playground/typescript-router-pinia/src/main.ts new file mode 100644 index 000000000..5dcad83c3 --- /dev/null +++ b/playground/typescript-router-pinia/src/main.ts @@ -0,0 +1,14 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router-pinia/src/router/index.ts b/playground/typescript-router-pinia/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router-pinia/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router-pinia/src/stores/counter.ts b/playground/typescript-router-pinia/src/stores/counter.ts new file mode 100644 index 000000000..b6757ba57 --- /dev/null +++ b/playground/typescript-router-pinia/src/stores/counter.ts @@ -0,0 +1,12 @@ +import { ref, computed } from 'vue' +import { defineStore } from 'pinia' + +export const useCounterStore = defineStore('counter', () => { + const count = ref(0) + const doubleCount = computed(() => count.value * 2) + function increment() { + count.value++ + } + + return { count, doubleCount, increment } +}) diff --git a/playground/typescript-router-pinia/src/views/AboutView.vue b/playground/typescript-router-pinia/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router-pinia/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router-pinia/src/views/HomeView.vue b/playground/typescript-router-pinia/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router-pinia/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router-pinia/tsconfig.app.json b/playground/typescript-router-pinia/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router-pinia/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router-pinia/tsconfig.json b/playground/typescript-router-pinia/tsconfig.json new file mode 100644 index 000000000..66b5e5703 --- /dev/null +++ b/playground/typescript-router-pinia/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/playground/typescript-router-pinia/tsconfig.node.json b/playground/typescript-router-pinia/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router-pinia/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router-pinia/vite.config.ts b/playground/typescript-router-pinia/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-router-pinia/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-playwright/.gitignore b/playground/typescript-router-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/typescript-router-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/typescript-router-playwright/.vscode/extensions.json b/playground/typescript-router-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/typescript-router-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/typescript-router-playwright/README.md b/playground/typescript-router-playwright/README.md new file mode 100644 index 000000000..66baddb01 --- /dev/null +++ b/playground/typescript-router-playwright/README.md @@ -0,0 +1,59 @@ +# typescript-router-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/typescript-router-playwright/e2e/tsconfig.json b/playground/typescript-router-playwright/e2e/tsconfig.json new file mode 100644 index 000000000..be3bbfc0e --- /dev/null +++ b/playground/typescript-router-playwright/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": ["./**/*"] +} diff --git a/playground/typescript-router-playwright/e2e/vue.spec.ts b/playground/typescript-router-playwright/e2e/vue.spec.ts new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/typescript-router-playwright/e2e/vue.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/typescript-router-playwright/env.d.ts b/playground/typescript-router-playwright/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router-playwright/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router-playwright/index.html b/playground/typescript-router-playwright/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router-playwright/package.json b/playground/typescript-router-playwright/package.json new file mode 100644 index 000000000..a61f6c005 --- /dev/null +++ b/playground/typescript-router-playwright/package.json @@ -0,0 +1,29 @@ +{ + "name": "typescript-router-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:e2e": "playwright test", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router-playwright/playwright.config.ts b/playground/typescript-router-playwright/playwright.config.ts new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/typescript-router-playwright/playwright.config.ts @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/typescript-router-playwright/public/favicon.ico b/playground/typescript-router-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router-playwright/src/App.vue b/playground/typescript-router-playwright/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router-playwright/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router-playwright/src/assets/logo.svg b/playground/typescript-router-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router-playwright/src/assets/main.css b/playground/typescript-router-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router-playwright/src/components/HelloWorld.vue b/playground/typescript-router-playwright/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router-playwright/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router-playwright/src/components/TheWelcome.vue b/playground/typescript-router-playwright/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router-playwright/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router-playwright/src/components/WelcomeItem.vue b/playground/typescript-router-playwright/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router-playwright/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router-playwright/src/components/icons/IconCommunity.vue b/playground/typescript-router-playwright/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router-playwright/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-playwright/src/components/icons/IconDocumentation.vue b/playground/typescript-router-playwright/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router-playwright/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-playwright/src/components/icons/IconEcosystem.vue b/playground/typescript-router-playwright/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router-playwright/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-playwright/src/components/icons/IconSupport.vue b/playground/typescript-router-playwright/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router-playwright/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-playwright/src/components/icons/IconTooling.vue b/playground/typescript-router-playwright/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router-playwright/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router-playwright/src/main.ts b/playground/typescript-router-playwright/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-router-playwright/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router-playwright/src/router/index.ts b/playground/typescript-router-playwright/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router-playwright/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router-playwright/src/views/AboutView.vue b/playground/typescript-router-playwright/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router-playwright/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router-playwright/src/views/HomeView.vue b/playground/typescript-router-playwright/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router-playwright/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router-playwright/tsconfig.app.json b/playground/typescript-router-playwright/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router-playwright/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router-playwright/tsconfig.json b/playground/typescript-router-playwright/tsconfig.json new file mode 100644 index 000000000..66b5e5703 --- /dev/null +++ b/playground/typescript-router-playwright/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/playground/typescript-router-playwright/tsconfig.node.json b/playground/typescript-router-playwright/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router-playwright/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router-playwright/vite.config.ts b/playground/typescript-router-playwright/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-router-playwright/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-vitest-cypress/.gitignore b/playground/typescript-router-vitest-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-router-vitest-cypress/README.md b/playground/typescript-router-vitest-cypress/README.md new file mode 100644 index 000000000..1766beb75 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/README.md @@ -0,0 +1,62 @@ +# typescript-router-vitest-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-router-vitest-cypress/cypress.config.ts b/playground/typescript-router-vitest-cypress/cypress.config.ts new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/typescript-router-vitest-cypress/cypress.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/typescript-router-vitest-cypress/cypress/e2e/example.cy.ts b/playground/typescript-router-vitest-cypress/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-router-vitest-cypress/cypress/e2e/tsconfig.json b/playground/typescript-router-vitest-cypress/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-router-vitest-cypress/cypress/fixtures/example.json b/playground/typescript-router-vitest-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-router-vitest-cypress/cypress/support/commands.ts b/playground/typescript-router-vitest-cypress/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-router-vitest-cypress/cypress/support/e2e.ts b/playground/typescript-router-vitest-cypress/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-router-vitest-cypress/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-router-vitest-cypress/env.d.ts b/playground/typescript-router-vitest-cypress/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router-vitest-cypress/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router-vitest-cypress/index.html b/playground/typescript-router-vitest-cypress/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router-vitest-cypress/package.json b/playground/typescript-router-vitest-cypress/package.json new file mode 100644 index 000000000..3986af842 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/package.json @@ -0,0 +1,36 @@ +{ + "name": "typescript-router-vitest-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router-vitest-cypress/public/favicon.ico b/playground/typescript-router-vitest-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router-vitest-cypress/src/App.vue b/playground/typescript-router-vitest-cypress/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router-vitest-cypress/src/assets/logo.svg b/playground/typescript-router-vitest-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router-vitest-cypress/src/assets/main.css b/playground/typescript-router-vitest-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router-vitest-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router-vitest-cypress/src/components/HelloWorld.vue b/playground/typescript-router-vitest-cypress/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router-vitest-cypress/src/components/TheWelcome.vue b/playground/typescript-router-vitest-cypress/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router-vitest-cypress/src/components/WelcomeItem.vue b/playground/typescript-router-vitest-cypress/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router-vitest-cypress/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-router-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-router-vitest-cypress/src/components/icons/IconCommunity.vue b/playground/typescript-router-vitest-cypress/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-vitest-cypress/src/components/icons/IconDocumentation.vue b/playground/typescript-router-vitest-cypress/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router-vitest-cypress/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-vitest-cypress/src/components/icons/IconEcosystem.vue b/playground/typescript-router-vitest-cypress/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router-vitest-cypress/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-vitest-cypress/src/components/icons/IconSupport.vue b/playground/typescript-router-vitest-cypress/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-vitest-cypress/src/components/icons/IconTooling.vue b/playground/typescript-router-vitest-cypress/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router-vitest-cypress/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router-vitest-cypress/src/main.ts b/playground/typescript-router-vitest-cypress/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router-vitest-cypress/src/router/index.ts b/playground/typescript-router-vitest-cypress/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router-vitest-cypress/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router-vitest-cypress/src/views/AboutView.vue b/playground/typescript-router-vitest-cypress/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router-vitest-cypress/src/views/HomeView.vue b/playground/typescript-router-vitest-cypress/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router-vitest-cypress/tsconfig.app.json b/playground/typescript-router-vitest-cypress/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router-vitest-cypress/tsconfig.json b/playground/typescript-router-vitest-cypress/tsconfig.json new file mode 100644 index 000000000..5304731b8 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-router-vitest-cypress/tsconfig.node.json b/playground/typescript-router-vitest-cypress/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router-vitest-cypress/tsconfig.vitest.json b/playground/typescript-router-vitest-cypress/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-router-vitest-cypress/vite.config.ts b/playground/typescript-router-vitest-cypress/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-router-vitest-cypress/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-vitest-cypress/vitest.config.ts b/playground/typescript-router-vitest-cypress/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-router-vitest-cypress/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-router-vitest-nightwatch/.gitignore b/playground/typescript-router-vitest-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/typescript-router-vitest-nightwatch/.vscode/extensions.json b/playground/typescript-router-vitest-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/typescript-router-vitest-nightwatch/README.md b/playground/typescript-router-vitest-nightwatch/README.md new file mode 100644 index 000000000..0fab55c12 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/README.md @@ -0,0 +1,69 @@ +# typescript-router-vitest-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/typescript-router-vitest-nightwatch/env.d.ts b/playground/typescript-router-vitest-nightwatch/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router-vitest-nightwatch/index.html b/playground/typescript-router-vitest-nightwatch/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router-vitest-nightwatch/nightwatch.conf.cjs b/playground/typescript-router-vitest-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/typescript-router-vitest-nightwatch/nightwatch/nightwatch.d.ts b/playground/typescript-router-vitest-nightwatch/nightwatch/nightwatch.d.ts new file mode 100644 index 000000000..616e63f9f --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/nightwatch/nightwatch.d.ts @@ -0,0 +1,13 @@ +import { NightwatchCustomAssertions, NightwatchCustomCommands } from 'nightwatch' + +declare module 'nightwatch' { + interface NightwatchCustomAssertions { + // Add your custom assertions' types here + // elementHasCount: (selector: string, count: number) => NightwatchBrowser + } + + interface NightwatchCustomCommands { + // Add your custom commands' types here + // strictClick: (selector: string) => NightwatchBrowser + } +} diff --git a/playground/typescript-router-vitest-nightwatch/nightwatch/tsconfig.json b/playground/typescript-router-vitest-nightwatch/nightwatch/tsconfig.json new file mode 100644 index 000000000..8cd7ca1da --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/nightwatch/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "../node_modules/.tmp/tsconfig.nightwatch.tsbuildinfo", + + "target": "ESNext", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": "../", + "lib": ["ESNext", "dom"], + "types": ["nightwatch"] + }, + "include": ["../node_modules/@nightwatch/**/*", "../src/components/**/*", "../tests/e2e/**/*"], + "ts-node": { + "transpileOnly": true + }, + "files": ["nightwatch.d.ts"] +} diff --git a/playground/typescript-router-vitest-nightwatch/package.json b/playground/typescript-router-vitest-nightwatch/package.json new file mode 100644 index 000000000..61bb96d9c --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/package.json @@ -0,0 +1,39 @@ +{ + "name": "typescript-router-vitest-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "nightwatch tests/e2e/*", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "jsdom": "^24.0.0", + "nightwatch": "^3.4.0", + "npm-run-all2": "^6.1.2", + "ts-node": "^10.9.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router-vitest-nightwatch/public/favicon.ico b/playground/typescript-router-vitest-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router-vitest-nightwatch/src/App.vue b/playground/typescript-router-vitest-nightwatch/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router-vitest-nightwatch/src/assets/logo.svg b/playground/typescript-router-vitest-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router-vitest-nightwatch/src/assets/main.css b/playground/typescript-router-vitest-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router-vitest-nightwatch/src/components/HelloWorld.vue b/playground/typescript-router-vitest-nightwatch/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router-vitest-nightwatch/src/components/TheWelcome.vue b/playground/typescript-router-vitest-nightwatch/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router-vitest-nightwatch/src/components/WelcomeItem.vue b/playground/typescript-router-vitest-nightwatch/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-router-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-router-vitest-nightwatch/src/components/icons/IconCommunity.vue b/playground/typescript-router-vitest-nightwatch/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-vitest-nightwatch/src/components/icons/IconDocumentation.vue b/playground/typescript-router-vitest-nightwatch/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-vitest-nightwatch/src/components/icons/IconEcosystem.vue b/playground/typescript-router-vitest-nightwatch/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-vitest-nightwatch/src/components/icons/IconSupport.vue b/playground/typescript-router-vitest-nightwatch/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-vitest-nightwatch/src/components/icons/IconTooling.vue b/playground/typescript-router-vitest-nightwatch/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router-vitest-nightwatch/src/main.ts b/playground/typescript-router-vitest-nightwatch/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router-vitest-nightwatch/src/router/index.ts b/playground/typescript-router-vitest-nightwatch/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router-vitest-nightwatch/src/views/AboutView.vue b/playground/typescript-router-vitest-nightwatch/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router-vitest-nightwatch/src/views/HomeView.vue b/playground/typescript-router-vitest-nightwatch/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router-vitest-nightwatch/tests/e2e/example.ts b/playground/typescript-router-vitest-nightwatch/tests/e2e/example.ts new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/tests/e2e/example.ts @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-router-vitest-nightwatch/tsconfig.app.json b/playground/typescript-router-vitest-nightwatch/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router-vitest-nightwatch/tsconfig.json b/playground/typescript-router-vitest-nightwatch/tsconfig.json new file mode 100644 index 000000000..a5352e667 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + }, + { + "path": "./nightwatch/tsconfig.json" + } + ] +} diff --git a/playground/typescript-router-vitest-nightwatch/tsconfig.node.json b/playground/typescript-router-vitest-nightwatch/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router-vitest-nightwatch/tsconfig.vitest.json b/playground/typescript-router-vitest-nightwatch/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-router-vitest-nightwatch/vite.config.ts b/playground/typescript-router-vitest-nightwatch/vite.config.ts new file mode 100644 index 000000000..be3cb9c57 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + nightwatchPlugin(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-vitest-nightwatch/vitest.config.ts b/playground/typescript-router-vitest-nightwatch/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-router-vitest-nightwatch/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-router-vitest-playwright/.gitignore b/playground/typescript-router-vitest-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/typescript-router-vitest-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/typescript-router-vitest-playwright/.vscode/extensions.json b/playground/typescript-router-vitest-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/typescript-router-vitest-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/typescript-router-vitest-playwright/README.md b/playground/typescript-router-vitest-playwright/README.md new file mode 100644 index 000000000..ab27a98ef --- /dev/null +++ b/playground/typescript-router-vitest-playwright/README.md @@ -0,0 +1,65 @@ +# typescript-router-vitest-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/typescript-router-vitest-playwright/e2e/tsconfig.json b/playground/typescript-router-vitest-playwright/e2e/tsconfig.json new file mode 100644 index 000000000..be3bbfc0e --- /dev/null +++ b/playground/typescript-router-vitest-playwright/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": ["./**/*"] +} diff --git a/playground/typescript-router-vitest-playwright/e2e/vue.spec.ts b/playground/typescript-router-vitest-playwright/e2e/vue.spec.ts new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/typescript-router-vitest-playwright/e2e/vue.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/typescript-router-vitest-playwright/env.d.ts b/playground/typescript-router-vitest-playwright/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router-vitest-playwright/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router-vitest-playwright/index.html b/playground/typescript-router-vitest-playwright/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router-vitest-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router-vitest-playwright/package.json b/playground/typescript-router-vitest-playwright/package.json new file mode 100644 index 000000000..d331ae45e --- /dev/null +++ b/playground/typescript-router-vitest-playwright/package.json @@ -0,0 +1,34 @@ +{ + "name": "typescript-router-vitest-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "playwright test", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router-vitest-playwright/playwright.config.ts b/playground/typescript-router-vitest-playwright/playwright.config.ts new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/typescript-router-vitest-playwright/playwright.config.ts @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/typescript-router-vitest-playwright/public/favicon.ico b/playground/typescript-router-vitest-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router-vitest-playwright/src/App.vue b/playground/typescript-router-vitest-playwright/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router-vitest-playwright/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router-vitest-playwright/src/assets/logo.svg b/playground/typescript-router-vitest-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router-vitest-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router-vitest-playwright/src/assets/main.css b/playground/typescript-router-vitest-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router-vitest-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router-vitest-playwright/src/components/HelloWorld.vue b/playground/typescript-router-vitest-playwright/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router-vitest-playwright/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router-vitest-playwright/src/components/TheWelcome.vue b/playground/typescript-router-vitest-playwright/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router-vitest-playwright/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router-vitest-playwright/src/components/WelcomeItem.vue b/playground/typescript-router-vitest-playwright/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router-vitest-playwright/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-router-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-router-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-router-vitest-playwright/src/components/icons/IconCommunity.vue b/playground/typescript-router-vitest-playwright/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router-vitest-playwright/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-vitest-playwright/src/components/icons/IconDocumentation.vue b/playground/typescript-router-vitest-playwright/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router-vitest-playwright/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-vitest-playwright/src/components/icons/IconEcosystem.vue b/playground/typescript-router-vitest-playwright/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router-vitest-playwright/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-vitest-playwright/src/components/icons/IconSupport.vue b/playground/typescript-router-vitest-playwright/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router-vitest-playwright/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-vitest-playwright/src/components/icons/IconTooling.vue b/playground/typescript-router-vitest-playwright/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router-vitest-playwright/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router-vitest-playwright/src/main.ts b/playground/typescript-router-vitest-playwright/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-router-vitest-playwright/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router-vitest-playwright/src/router/index.ts b/playground/typescript-router-vitest-playwright/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router-vitest-playwright/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router-vitest-playwright/src/views/AboutView.vue b/playground/typescript-router-vitest-playwright/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router-vitest-playwright/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router-vitest-playwright/src/views/HomeView.vue b/playground/typescript-router-vitest-playwright/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router-vitest-playwright/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router-vitest-playwright/tsconfig.app.json b/playground/typescript-router-vitest-playwright/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router-vitest-playwright/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router-vitest-playwright/tsconfig.json b/playground/typescript-router-vitest-playwright/tsconfig.json new file mode 100644 index 000000000..100cf6a8f --- /dev/null +++ b/playground/typescript-router-vitest-playwright/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ] +} diff --git a/playground/typescript-router-vitest-playwright/tsconfig.node.json b/playground/typescript-router-vitest-playwright/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router-vitest-playwright/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router-vitest-playwright/tsconfig.vitest.json b/playground/typescript-router-vitest-playwright/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-router-vitest-playwright/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-router-vitest-playwright/vite.config.ts b/playground/typescript-router-vitest-playwright/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-router-vitest-playwright/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-vitest-playwright/vitest.config.ts b/playground/typescript-router-vitest-playwright/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-router-vitest-playwright/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-router-vitest/.gitignore b/playground/typescript-router-vitest/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-router-vitest/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-router-vitest/README.md b/playground/typescript-router-vitest/README.md new file mode 100644 index 000000000..730ad8fc1 --- /dev/null +++ b/playground/typescript-router-vitest/README.md @@ -0,0 +1,46 @@ +# typescript-router-vitest + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` diff --git a/playground/typescript-router-vitest/env.d.ts b/playground/typescript-router-vitest/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router-vitest/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router-vitest/index.html b/playground/typescript-router-vitest/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router-vitest/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router-vitest/package.json b/playground/typescript-router-vitest/package.json new file mode 100644 index 000000000..78a6ba8d6 --- /dev/null +++ b/playground/typescript-router-vitest/package.json @@ -0,0 +1,32 @@ +{ + "name": "typescript-router-vitest", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router-vitest/public/favicon.ico b/playground/typescript-router-vitest/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router-vitest/src/App.vue b/playground/typescript-router-vitest/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router-vitest/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router-vitest/src/assets/logo.svg b/playground/typescript-router-vitest/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router-vitest/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router-vitest/src/assets/main.css b/playground/typescript-router-vitest/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router-vitest/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router-vitest/src/components/HelloWorld.vue b/playground/typescript-router-vitest/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router-vitest/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router-vitest/src/components/TheWelcome.vue b/playground/typescript-router-vitest/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router-vitest/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router-vitest/src/components/WelcomeItem.vue b/playground/typescript-router-vitest/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router-vitest/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router-vitest/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-router-vitest/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-router-vitest/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-router-vitest/src/components/icons/IconCommunity.vue b/playground/typescript-router-vitest/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router-vitest/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-vitest/src/components/icons/IconDocumentation.vue b/playground/typescript-router-vitest/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router-vitest/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-vitest/src/components/icons/IconEcosystem.vue b/playground/typescript-router-vitest/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router-vitest/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-vitest/src/components/icons/IconSupport.vue b/playground/typescript-router-vitest/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router-vitest/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-vitest/src/components/icons/IconTooling.vue b/playground/typescript-router-vitest/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router-vitest/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router-vitest/src/main.ts b/playground/typescript-router-vitest/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-router-vitest/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router-vitest/src/router/index.ts b/playground/typescript-router-vitest/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router-vitest/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router-vitest/src/views/AboutView.vue b/playground/typescript-router-vitest/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router-vitest/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router-vitest/src/views/HomeView.vue b/playground/typescript-router-vitest/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router-vitest/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router-vitest/tsconfig.app.json b/playground/typescript-router-vitest/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router-vitest/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router-vitest/tsconfig.json b/playground/typescript-router-vitest/tsconfig.json new file mode 100644 index 000000000..100cf6a8f --- /dev/null +++ b/playground/typescript-router-vitest/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ] +} diff --git a/playground/typescript-router-vitest/tsconfig.node.json b/playground/typescript-router-vitest/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router-vitest/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router-vitest/tsconfig.vitest.json b/playground/typescript-router-vitest/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-router-vitest/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-router-vitest/vite.config.ts b/playground/typescript-router-vitest/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-router-vitest/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-vitest/vitest.config.ts b/playground/typescript-router-vitest/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-router-vitest/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-router-with-tests/.gitignore b/playground/typescript-router-with-tests/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-router-with-tests/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-router-with-tests/README.md b/playground/typescript-router-with-tests/README.md new file mode 100644 index 000000000..4b1d6d9db --- /dev/null +++ b/playground/typescript-router-with-tests/README.md @@ -0,0 +1,62 @@ +# typescript-router-with-tests + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-router-with-tests/cypress.config.ts b/playground/typescript-router-with-tests/cypress.config.ts new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/typescript-router-with-tests/cypress.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/typescript-router-with-tests/cypress/e2e/example.cy.ts b/playground/typescript-router-with-tests/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-router-with-tests/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-router-with-tests/cypress/e2e/tsconfig.json b/playground/typescript-router-with-tests/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-router-with-tests/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-router-with-tests/cypress/fixtures/example.json b/playground/typescript-router-with-tests/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-router-with-tests/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-router-with-tests/cypress/support/commands.ts b/playground/typescript-router-with-tests/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-router-with-tests/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-router-with-tests/cypress/support/e2e.ts b/playground/typescript-router-with-tests/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-router-with-tests/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-router-with-tests/env.d.ts b/playground/typescript-router-with-tests/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router-with-tests/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router-with-tests/index.html b/playground/typescript-router-with-tests/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router-with-tests/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router-with-tests/package.json b/playground/typescript-router-with-tests/package.json new file mode 100644 index 000000000..935dfbea7 --- /dev/null +++ b/playground/typescript-router-with-tests/package.json @@ -0,0 +1,36 @@ +{ + "name": "typescript-router-with-tests", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router-with-tests/public/favicon.ico b/playground/typescript-router-with-tests/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router-with-tests/src/App.vue b/playground/typescript-router-with-tests/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router-with-tests/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router-with-tests/src/assets/logo.svg b/playground/typescript-router-with-tests/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router-with-tests/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router-with-tests/src/assets/main.css b/playground/typescript-router-with-tests/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router-with-tests/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router-with-tests/src/components/HelloWorld.vue b/playground/typescript-router-with-tests/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router-with-tests/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router-with-tests/src/components/TheWelcome.vue b/playground/typescript-router-with-tests/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router-with-tests/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router-with-tests/src/components/WelcomeItem.vue b/playground/typescript-router-with-tests/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router-with-tests/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router-with-tests/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-router-with-tests/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-router-with-tests/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-router-with-tests/src/components/icons/IconCommunity.vue b/playground/typescript-router-with-tests/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router-with-tests/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-with-tests/src/components/icons/IconDocumentation.vue b/playground/typescript-router-with-tests/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router-with-tests/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-with-tests/src/components/icons/IconEcosystem.vue b/playground/typescript-router-with-tests/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router-with-tests/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-with-tests/src/components/icons/IconSupport.vue b/playground/typescript-router-with-tests/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router-with-tests/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router-with-tests/src/components/icons/IconTooling.vue b/playground/typescript-router-with-tests/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router-with-tests/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router-with-tests/src/main.ts b/playground/typescript-router-with-tests/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-router-with-tests/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router-with-tests/src/router/index.ts b/playground/typescript-router-with-tests/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router-with-tests/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router-with-tests/src/views/AboutView.vue b/playground/typescript-router-with-tests/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router-with-tests/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router-with-tests/src/views/HomeView.vue b/playground/typescript-router-with-tests/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router-with-tests/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router-with-tests/tsconfig.app.json b/playground/typescript-router-with-tests/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router-with-tests/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router-with-tests/tsconfig.json b/playground/typescript-router-with-tests/tsconfig.json new file mode 100644 index 000000000..5304731b8 --- /dev/null +++ b/playground/typescript-router-with-tests/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-router-with-tests/tsconfig.node.json b/playground/typescript-router-with-tests/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router-with-tests/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router-with-tests/tsconfig.vitest.json b/playground/typescript-router-with-tests/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-router-with-tests/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-router-with-tests/vite.config.ts b/playground/typescript-router-with-tests/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-router-with-tests/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-router-with-tests/vitest.config.ts b/playground/typescript-router-with-tests/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-router-with-tests/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-router/.gitignore b/playground/typescript-router/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-router/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-router/README.md b/playground/typescript-router/README.md new file mode 100644 index 000000000..3fd6ad110 --- /dev/null +++ b/playground/typescript-router/README.md @@ -0,0 +1,40 @@ +# typescript-router + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` diff --git a/playground/typescript-router/env.d.ts b/playground/typescript-router/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-router/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-router/index.html b/playground/typescript-router/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-router/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-router/package.json b/playground/typescript-router/package.json new file mode 100644 index 000000000..ad7f7341b --- /dev/null +++ b/playground/typescript-router/package.json @@ -0,0 +1,27 @@ +{ + "name": "typescript-router", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15", + "vue-router": "^4.2.5" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-router/public/favicon.ico b/playground/typescript-router/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-router/src/App.vue b/playground/typescript-router/src/App.vue new file mode 100644 index 000000000..7905b0516 --- /dev/null +++ b/playground/typescript-router/src/App.vue @@ -0,0 +1,85 @@ + + + + + diff --git a/playground/typescript-router/src/assets/logo.svg b/playground/typescript-router/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-router/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-router/src/assets/main.css b/playground/typescript-router/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-router/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-router/src/components/HelloWorld.vue b/playground/typescript-router/src/components/HelloWorld.vue new file mode 100644 index 000000000..38d821ef8 --- /dev/null +++ b/playground/typescript-router/src/components/HelloWorld.vue @@ -0,0 +1,41 @@ + + + + + diff --git a/playground/typescript-router/src/components/TheWelcome.vue b/playground/typescript-router/src/components/TheWelcome.vue new file mode 100644 index 000000000..49d8f7354 --- /dev/null +++ b/playground/typescript-router/src/components/TheWelcome.vue @@ -0,0 +1,88 @@ + + + diff --git a/playground/typescript-router/src/components/WelcomeItem.vue b/playground/typescript-router/src/components/WelcomeItem.vue new file mode 100644 index 000000000..6d7086aea --- /dev/null +++ b/playground/typescript-router/src/components/WelcomeItem.vue @@ -0,0 +1,87 @@ + + + diff --git a/playground/typescript-router/src/components/icons/IconCommunity.vue b/playground/typescript-router/src/components/icons/IconCommunity.vue new file mode 100644 index 000000000..2dc8b0552 --- /dev/null +++ b/playground/typescript-router/src/components/icons/IconCommunity.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router/src/components/icons/IconDocumentation.vue b/playground/typescript-router/src/components/icons/IconDocumentation.vue new file mode 100644 index 000000000..6d4791cfb --- /dev/null +++ b/playground/typescript-router/src/components/icons/IconDocumentation.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router/src/components/icons/IconEcosystem.vue b/playground/typescript-router/src/components/icons/IconEcosystem.vue new file mode 100644 index 000000000..c3a4f078c --- /dev/null +++ b/playground/typescript-router/src/components/icons/IconEcosystem.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router/src/components/icons/IconSupport.vue b/playground/typescript-router/src/components/icons/IconSupport.vue new file mode 100644 index 000000000..7452834d3 --- /dev/null +++ b/playground/typescript-router/src/components/icons/IconSupport.vue @@ -0,0 +1,7 @@ + diff --git a/playground/typescript-router/src/components/icons/IconTooling.vue b/playground/typescript-router/src/components/icons/IconTooling.vue new file mode 100644 index 000000000..660598d7c --- /dev/null +++ b/playground/typescript-router/src/components/icons/IconTooling.vue @@ -0,0 +1,19 @@ + + diff --git a/playground/typescript-router/src/main.ts b/playground/typescript-router/src/main.ts new file mode 100644 index 000000000..5a5dbdba7 --- /dev/null +++ b/playground/typescript-router/src/main.ts @@ -0,0 +1,11 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' +import router from './router' + +const app = createApp(App) + +app.use(router) + +app.mount('#app') diff --git a/playground/typescript-router/src/router/index.ts b/playground/typescript-router/src/router/index.ts new file mode 100644 index 000000000..a49ae507f --- /dev/null +++ b/playground/typescript-router/src/router/index.ts @@ -0,0 +1,23 @@ +import { createRouter, createWebHistory } from 'vue-router' +import HomeView from '../views/HomeView.vue' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/', + name: 'home', + component: HomeView + }, + { + path: '/about', + name: 'about', + // route level code-splitting + // this generates a separate chunk (About.[hash].js) for this route + // which is lazy-loaded when the route is visited. + component: () => import('../views/AboutView.vue') + } + ] +}) + +export default router diff --git a/playground/typescript-router/src/views/AboutView.vue b/playground/typescript-router/src/views/AboutView.vue new file mode 100644 index 000000000..756ad2a17 --- /dev/null +++ b/playground/typescript-router/src/views/AboutView.vue @@ -0,0 +1,15 @@ + + + diff --git a/playground/typescript-router/src/views/HomeView.vue b/playground/typescript-router/src/views/HomeView.vue new file mode 100644 index 000000000..d5c0217e4 --- /dev/null +++ b/playground/typescript-router/src/views/HomeView.vue @@ -0,0 +1,9 @@ + + + diff --git a/playground/typescript-router/tsconfig.app.json b/playground/typescript-router/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-router/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-router/tsconfig.json b/playground/typescript-router/tsconfig.json new file mode 100644 index 000000000..66b5e5703 --- /dev/null +++ b/playground/typescript-router/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/playground/typescript-router/tsconfig.node.json b/playground/typescript-router/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-router/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-router/vite.config.ts b/playground/typescript-router/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-router/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-vitest-cypress/.gitignore b/playground/typescript-vitest-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-vitest-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-vitest-cypress/README.md b/playground/typescript-vitest-cypress/README.md new file mode 100644 index 000000000..03d30ecc0 --- /dev/null +++ b/playground/typescript-vitest-cypress/README.md @@ -0,0 +1,62 @@ +# typescript-vitest-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-vitest-cypress/cypress.config.ts b/playground/typescript-vitest-cypress/cypress.config.ts new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/typescript-vitest-cypress/cypress.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/typescript-vitest-cypress/cypress/e2e/example.cy.ts b/playground/typescript-vitest-cypress/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-vitest-cypress/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-vitest-cypress/cypress/e2e/tsconfig.json b/playground/typescript-vitest-cypress/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-vitest-cypress/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-vitest-cypress/cypress/fixtures/example.json b/playground/typescript-vitest-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-vitest-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-vitest-cypress/cypress/support/commands.ts b/playground/typescript-vitest-cypress/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-vitest-cypress/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-vitest-cypress/cypress/support/e2e.ts b/playground/typescript-vitest-cypress/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-vitest-cypress/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-vitest-cypress/env.d.ts b/playground/typescript-vitest-cypress/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-vitest-cypress/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-vitest-cypress/index.html b/playground/typescript-vitest-cypress/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-vitest-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-vitest-cypress/package.json b/playground/typescript-vitest-cypress/package.json new file mode 100644 index 000000000..da4f4df97 --- /dev/null +++ b/playground/typescript-vitest-cypress/package.json @@ -0,0 +1,35 @@ +{ + "name": "typescript-vitest-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-vitest-cypress/public/favicon.ico b/playground/typescript-vitest-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-vitest-cypress/src/App.vue b/playground/typescript-vitest-cypress/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-vitest-cypress/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-vitest-cypress/src/assets/logo.svg b/playground/typescript-vitest-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-vitest-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-vitest-cypress/src/assets/main.css b/playground/typescript-vitest-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-vitest-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-vitest-cypress/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-vitest-cypress/src/main.ts b/playground/typescript-vitest-cypress/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript-vitest-cypress/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript-vitest-cypress/tsconfig.app.json b/playground/typescript-vitest-cypress/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-vitest-cypress/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-vitest-cypress/tsconfig.json b/playground/typescript-vitest-cypress/tsconfig.json new file mode 100644 index 000000000..5304731b8 --- /dev/null +++ b/playground/typescript-vitest-cypress/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-vitest-cypress/tsconfig.node.json b/playground/typescript-vitest-cypress/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-vitest-cypress/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-vitest-cypress/tsconfig.vitest.json b/playground/typescript-vitest-cypress/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-vitest-cypress/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-vitest-cypress/vite.config.ts b/playground/typescript-vitest-cypress/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-vitest-cypress/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-vitest-cypress/vitest.config.ts b/playground/typescript-vitest-cypress/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-vitest-cypress/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-vitest-nightwatch/.gitignore b/playground/typescript-vitest-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/typescript-vitest-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/typescript-vitest-nightwatch/.vscode/extensions.json b/playground/typescript-vitest-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/typescript-vitest-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/typescript-vitest-nightwatch/README.md b/playground/typescript-vitest-nightwatch/README.md new file mode 100644 index 000000000..f4abca0db --- /dev/null +++ b/playground/typescript-vitest-nightwatch/README.md @@ -0,0 +1,69 @@ +# typescript-vitest-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/typescript-vitest-nightwatch/env.d.ts b/playground/typescript-vitest-nightwatch/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-vitest-nightwatch/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-vitest-nightwatch/index.html b/playground/typescript-vitest-nightwatch/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-vitest-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-vitest-nightwatch/nightwatch.conf.cjs b/playground/typescript-vitest-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/typescript-vitest-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/typescript-vitest-nightwatch/nightwatch/nightwatch.d.ts b/playground/typescript-vitest-nightwatch/nightwatch/nightwatch.d.ts new file mode 100644 index 000000000..616e63f9f --- /dev/null +++ b/playground/typescript-vitest-nightwatch/nightwatch/nightwatch.d.ts @@ -0,0 +1,13 @@ +import { NightwatchCustomAssertions, NightwatchCustomCommands } from 'nightwatch' + +declare module 'nightwatch' { + interface NightwatchCustomAssertions { + // Add your custom assertions' types here + // elementHasCount: (selector: string, count: number) => NightwatchBrowser + } + + interface NightwatchCustomCommands { + // Add your custom commands' types here + // strictClick: (selector: string) => NightwatchBrowser + } +} diff --git a/playground/typescript-vitest-nightwatch/nightwatch/tsconfig.json b/playground/typescript-vitest-nightwatch/nightwatch/tsconfig.json new file mode 100644 index 000000000..8cd7ca1da --- /dev/null +++ b/playground/typescript-vitest-nightwatch/nightwatch/tsconfig.json @@ -0,0 +1,20 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "../node_modules/.tmp/tsconfig.nightwatch.tsbuildinfo", + + "target": "ESNext", + "module": "commonjs", + "moduleResolution": "node", + "rootDir": "../", + "lib": ["ESNext", "dom"], + "types": ["nightwatch"] + }, + "include": ["../node_modules/@nightwatch/**/*", "../src/components/**/*", "../tests/e2e/**/*"], + "ts-node": { + "transpileOnly": true + }, + "files": ["nightwatch.d.ts"] +} diff --git a/playground/typescript-vitest-nightwatch/package.json b/playground/typescript-vitest-nightwatch/package.json new file mode 100644 index 000000000..1522712ec --- /dev/null +++ b/playground/typescript-vitest-nightwatch/package.json @@ -0,0 +1,38 @@ +{ + "name": "typescript-vitest-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "nightwatch tests/e2e/*", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "jsdom": "^24.0.0", + "nightwatch": "^3.4.0", + "npm-run-all2": "^6.1.2", + "ts-node": "^10.9.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-vitest-nightwatch/public/favicon.ico b/playground/typescript-vitest-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-vitest-nightwatch/src/App.vue b/playground/typescript-vitest-nightwatch/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-vitest-nightwatch/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-vitest-nightwatch/src/assets/logo.svg b/playground/typescript-vitest-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-vitest-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-vitest-nightwatch/src/assets/main.css b/playground/typescript-vitest-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-vitest-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-vitest-nightwatch/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-vitest-nightwatch/src/main.ts b/playground/typescript-vitest-nightwatch/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript-vitest-nightwatch/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript-vitest-nightwatch/tests/e2e/example.ts b/playground/typescript-vitest-nightwatch/tests/e2e/example.ts new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/typescript-vitest-nightwatch/tests/e2e/example.ts @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/typescript-vitest-nightwatch/tsconfig.app.json b/playground/typescript-vitest-nightwatch/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-vitest-nightwatch/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-vitest-nightwatch/tsconfig.json b/playground/typescript-vitest-nightwatch/tsconfig.json new file mode 100644 index 000000000..a5352e667 --- /dev/null +++ b/playground/typescript-vitest-nightwatch/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + }, + { + "path": "./nightwatch/tsconfig.json" + } + ] +} diff --git a/playground/typescript-vitest-nightwatch/tsconfig.node.json b/playground/typescript-vitest-nightwatch/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-vitest-nightwatch/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-vitest-nightwatch/tsconfig.vitest.json b/playground/typescript-vitest-nightwatch/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-vitest-nightwatch/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-vitest-nightwatch/vite.config.ts b/playground/typescript-vitest-nightwatch/vite.config.ts new file mode 100644 index 000000000..be3cb9c57 --- /dev/null +++ b/playground/typescript-vitest-nightwatch/vite.config.ts @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + nightwatchPlugin(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-vitest-nightwatch/vitest.config.ts b/playground/typescript-vitest-nightwatch/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-vitest-nightwatch/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-vitest-playwright/.gitignore b/playground/typescript-vitest-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/typescript-vitest-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/typescript-vitest-playwright/.vscode/extensions.json b/playground/typescript-vitest-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/typescript-vitest-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/typescript-vitest-playwright/README.md b/playground/typescript-vitest-playwright/README.md new file mode 100644 index 000000000..cdad7621b --- /dev/null +++ b/playground/typescript-vitest-playwright/README.md @@ -0,0 +1,65 @@ +# typescript-vitest-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/typescript-vitest-playwright/e2e/tsconfig.json b/playground/typescript-vitest-playwright/e2e/tsconfig.json new file mode 100644 index 000000000..be3bbfc0e --- /dev/null +++ b/playground/typescript-vitest-playwright/e2e/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": ["./**/*"] +} diff --git a/playground/typescript-vitest-playwright/e2e/vue.spec.ts b/playground/typescript-vitest-playwright/e2e/vue.spec.ts new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/typescript-vitest-playwright/e2e/vue.spec.ts @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/typescript-vitest-playwright/env.d.ts b/playground/typescript-vitest-playwright/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-vitest-playwright/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-vitest-playwright/index.html b/playground/typescript-vitest-playwright/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-vitest-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-vitest-playwright/package.json b/playground/typescript-vitest-playwright/package.json new file mode 100644 index 000000000..d8b6030cf --- /dev/null +++ b/playground/typescript-vitest-playwright/package.json @@ -0,0 +1,33 @@ +{ + "name": "typescript-vitest-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "playwright test", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-vitest-playwright/playwright.config.ts b/playground/typescript-vitest-playwright/playwright.config.ts new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/typescript-vitest-playwright/playwright.config.ts @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/typescript-vitest-playwright/public/favicon.ico b/playground/typescript-vitest-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-vitest-playwright/src/App.vue b/playground/typescript-vitest-playwright/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-vitest-playwright/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-vitest-playwright/src/assets/logo.svg b/playground/typescript-vitest-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-vitest-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-vitest-playwright/src/assets/main.css b/playground/typescript-vitest-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-vitest-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-vitest-playwright/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-vitest-playwright/src/main.ts b/playground/typescript-vitest-playwright/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript-vitest-playwright/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript-vitest-playwright/tsconfig.app.json b/playground/typescript-vitest-playwright/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-vitest-playwright/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-vitest-playwright/tsconfig.json b/playground/typescript-vitest-playwright/tsconfig.json new file mode 100644 index 000000000..100cf6a8f --- /dev/null +++ b/playground/typescript-vitest-playwright/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ] +} diff --git a/playground/typescript-vitest-playwright/tsconfig.node.json b/playground/typescript-vitest-playwright/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-vitest-playwright/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-vitest-playwright/tsconfig.vitest.json b/playground/typescript-vitest-playwright/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-vitest-playwright/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-vitest-playwright/vite.config.ts b/playground/typescript-vitest-playwright/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-vitest-playwright/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-vitest-playwright/vitest.config.ts b/playground/typescript-vitest-playwright/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-vitest-playwright/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-vitest/.gitignore b/playground/typescript-vitest/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-vitest/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-vitest/README.md b/playground/typescript-vitest/README.md new file mode 100644 index 000000000..1a8cd39b1 --- /dev/null +++ b/playground/typescript-vitest/README.md @@ -0,0 +1,46 @@ +# typescript-vitest + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` diff --git a/playground/typescript-vitest/env.d.ts b/playground/typescript-vitest/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-vitest/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-vitest/index.html b/playground/typescript-vitest/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-vitest/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-vitest/package.json b/playground/typescript-vitest/package.json new file mode 100644 index 000000000..7fe9c424b --- /dev/null +++ b/playground/typescript-vitest/package.json @@ -0,0 +1,31 @@ +{ + "name": "typescript-vitest", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-vitest/public/favicon.ico b/playground/typescript-vitest/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-vitest/src/App.vue b/playground/typescript-vitest/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-vitest/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-vitest/src/assets/logo.svg b/playground/typescript-vitest/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-vitest/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-vitest/src/assets/main.css b/playground/typescript-vitest/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-vitest/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-vitest/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-vitest/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-vitest/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-vitest/src/main.ts b/playground/typescript-vitest/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript-vitest/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript-vitest/tsconfig.app.json b/playground/typescript-vitest/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-vitest/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-vitest/tsconfig.json b/playground/typescript-vitest/tsconfig.json new file mode 100644 index 000000000..100cf6a8f --- /dev/null +++ b/playground/typescript-vitest/tsconfig.json @@ -0,0 +1,14 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ] +} diff --git a/playground/typescript-vitest/tsconfig.node.json b/playground/typescript-vitest/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-vitest/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-vitest/tsconfig.vitest.json b/playground/typescript-vitest/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-vitest/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-vitest/vite.config.ts b/playground/typescript-vitest/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-vitest/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-vitest/vitest.config.ts b/playground/typescript-vitest/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-vitest/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript-with-tests/.gitignore b/playground/typescript-with-tests/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript-with-tests/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript-with-tests/README.md b/playground/typescript-with-tests/README.md new file mode 100644 index 000000000..feca9e189 --- /dev/null +++ b/playground/typescript-with-tests/README.md @@ -0,0 +1,62 @@ +# typescript-with-tests + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/typescript-with-tests/cypress.config.ts b/playground/typescript-with-tests/cypress.config.ts new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/typescript-with-tests/cypress.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/typescript-with-tests/cypress/e2e/example.cy.ts b/playground/typescript-with-tests/cypress/e2e/example.cy.ts new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/typescript-with-tests/cypress/e2e/example.cy.ts @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/typescript-with-tests/cypress/e2e/tsconfig.json b/playground/typescript-with-tests/cypress/e2e/tsconfig.json new file mode 100644 index 000000000..37748feb7 --- /dev/null +++ b/playground/typescript-with-tests/cypress/e2e/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["./**/*", "../support/**/*"], + "compilerOptions": { + "isolatedModules": false, + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + } +} diff --git a/playground/typescript-with-tests/cypress/fixtures/example.json b/playground/typescript-with-tests/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/typescript-with-tests/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/typescript-with-tests/cypress/support/commands.ts b/playground/typescript-with-tests/cypress/support/commands.ts new file mode 100644 index 000000000..9b7bb8e25 --- /dev/null +++ b/playground/typescript-with-tests/cypress/support/commands.ts @@ -0,0 +1,39 @@ +/// +// *********************************************** +// This example commands.ts shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) +// +// declare global { +// namespace Cypress { +// interface Chainable { +// login(email: string, password: string): Chainable +// drag(subject: string, options?: Partial): Chainable +// dismiss(subject: string, options?: Partial): Chainable +// visit(originalFn: CommandOriginalFn, url: string, options: Partial): Chainable +// } +// } +// } + +export {} diff --git a/playground/typescript-with-tests/cypress/support/e2e.ts b/playground/typescript-with-tests/cypress/support/e2e.ts new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/typescript-with-tests/cypress/support/e2e.ts @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/typescript-with-tests/env.d.ts b/playground/typescript-with-tests/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript-with-tests/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript-with-tests/index.html b/playground/typescript-with-tests/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript-with-tests/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript-with-tests/package.json b/playground/typescript-with-tests/package.json new file mode 100644 index 000000000..abc144c37 --- /dev/null +++ b/playground/typescript-with-tests/package.json @@ -0,0 +1,35 @@ +{ + "name": "typescript-with-tests", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/jsdom": "^21.1.6", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "@vue/tsconfig": "^0.5.1", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "npm-run-all2": "^6.1.2", + "start-server-and-test": "^2.0.3", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vitest": "^1.2.2", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript-with-tests/public/favicon.ico b/playground/typescript-with-tests/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript-with-tests/src/App.vue b/playground/typescript-with-tests/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript-with-tests/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript-with-tests/src/assets/logo.svg b/playground/typescript-with-tests/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript-with-tests/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript-with-tests/src/assets/main.css b/playground/typescript-with-tests/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript-with-tests/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript-with-tests/src/components/__tests__/HelloWorld.spec.ts b/playground/typescript-with-tests/src/components/__tests__/HelloWorld.spec.ts new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/typescript-with-tests/src/components/__tests__/HelloWorld.spec.ts @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/typescript-with-tests/src/main.ts b/playground/typescript-with-tests/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript-with-tests/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript-with-tests/tsconfig.app.json b/playground/typescript-with-tests/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript-with-tests/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript-with-tests/tsconfig.json b/playground/typescript-with-tests/tsconfig.json new file mode 100644 index 000000000..5304731b8 --- /dev/null +++ b/playground/typescript-with-tests/tsconfig.json @@ -0,0 +1,17 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + }, + { + "path": "./tsconfig.vitest.json" + } + ], + "compilerOptions": { + "module": "NodeNext" + } +} diff --git a/playground/typescript-with-tests/tsconfig.node.json b/playground/typescript-with-tests/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript-with-tests/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript-with-tests/tsconfig.vitest.json b/playground/typescript-with-tests/tsconfig.vitest.json new file mode 100644 index 000000000..571995d11 --- /dev/null +++ b/playground/typescript-with-tests/tsconfig.vitest.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.app.json", + "exclude": [], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.vitest.tsbuildinfo", + + "lib": [], + "types": ["node", "jsdom"] + } +} diff --git a/playground/typescript-with-tests/vite.config.ts b/playground/typescript-with-tests/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript-with-tests/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/typescript-with-tests/vitest.config.ts b/playground/typescript-with-tests/vitest.config.ts new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/typescript-with-tests/vitest.config.ts @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/typescript/.gitignore b/playground/typescript/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/typescript/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/typescript/README.md b/playground/typescript/README.md new file mode 100644 index 000000000..734ce2d16 --- /dev/null +++ b/playground/typescript/README.md @@ -0,0 +1,40 @@ +# typescript + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types. + +If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps: + +1. Disable the built-in TypeScript Extension + 1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette + 2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)` +2. Reload the VSCode window by running `Developer: Reload Window` from the command palette. + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +pnpm build +``` diff --git a/playground/typescript/env.d.ts b/playground/typescript/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/playground/typescript/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/playground/typescript/index.html b/playground/typescript/index.html new file mode 100644 index 000000000..a88854489 --- /dev/null +++ b/playground/typescript/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/typescript/package.json b/playground/typescript/package.json new file mode 100644 index 000000000..bf0b73354 --- /dev/null +++ b/playground/typescript/package.json @@ -0,0 +1,26 @@ +{ + "name": "typescript", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build --force" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@tsconfig/node20": "^20.1.2", + "@types/node": "^20.11.16", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/tsconfig": "^0.5.1", + "npm-run-all2": "^6.1.2", + "typescript": "~5.3.0", + "vite": "^5.0.11", + "vue-tsc": "^1.8.27" + } +} diff --git a/playground/typescript/public/favicon.ico b/playground/typescript/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/typescript/src/App.vue b/playground/typescript/src/App.vue new file mode 100644 index 000000000..69f32f91f --- /dev/null +++ b/playground/typescript/src/App.vue @@ -0,0 +1,10 @@ + + + + + diff --git a/playground/typescript/src/assets/logo.svg b/playground/typescript/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/typescript/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/typescript/src/assets/main.css b/playground/typescript/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/typescript/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/typescript/src/main.ts b/playground/typescript/src/main.ts new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/typescript/src/main.ts @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/typescript/tsconfig.app.json b/playground/typescript/tsconfig.app.json new file mode 100644 index 000000000..e14c754d3 --- /dev/null +++ b/playground/typescript/tsconfig.app.json @@ -0,0 +1,14 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + "composite": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + } +} diff --git a/playground/typescript/tsconfig.json b/playground/typescript/tsconfig.json new file mode 100644 index 000000000..66b5e5703 --- /dev/null +++ b/playground/typescript/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/playground/typescript/tsconfig.node.json b/playground/typescript/tsconfig.node.json new file mode 100644 index 000000000..f09406303 --- /dev/null +++ b/playground/typescript/tsconfig.node.json @@ -0,0 +1,19 @@ +{ + "extends": "@tsconfig/node20/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "nightwatch.conf.*", + "playwright.config.*" + ], + "compilerOptions": { + "composite": true, + "noEmit": true, + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + + "module": "ESNext", + "moduleResolution": "Bundler", + "types": ["node"] + } +} diff --git a/playground/typescript/vite.config.ts b/playground/typescript/vite.config.ts new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/typescript/vite.config.ts @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/vitest-cypress/.gitignore b/playground/vitest-cypress/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/vitest-cypress/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/vitest-cypress/README.md b/playground/vitest-cypress/README.md new file mode 100644 index 000000000..e02686273 --- /dev/null +++ b/playground/vitest-cypress/README.md @@ -0,0 +1,51 @@ +# vitest-cypress + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/vitest-cypress/cypress.config.js b/playground/vitest-cypress/cypress.config.js new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/vitest-cypress/cypress.config.js @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/vitest-cypress/cypress/e2e/example.cy.js b/playground/vitest-cypress/cypress/e2e/example.cy.js new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/vitest-cypress/cypress/e2e/example.cy.js @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/vitest-cypress/cypress/e2e/jsconfig.json b/playground/vitest-cypress/cypress/e2e/jsconfig.json new file mode 100644 index 000000000..c790a70d6 --- /dev/null +++ b/playground/vitest-cypress/cypress/e2e/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + }, + "include": ["./**/*", "../support/**/*"] +} diff --git a/playground/vitest-cypress/cypress/fixtures/example.json b/playground/vitest-cypress/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/vitest-cypress/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/vitest-cypress/cypress/support/commands.js b/playground/vitest-cypress/cypress/support/commands.js new file mode 100644 index 000000000..119ab03f7 --- /dev/null +++ b/playground/vitest-cypress/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) diff --git a/playground/vitest-cypress/cypress/support/e2e.js b/playground/vitest-cypress/cypress/support/e2e.js new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/vitest-cypress/cypress/support/e2e.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/vitest-cypress/index.html b/playground/vitest-cypress/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/vitest-cypress/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/vitest-cypress/jsconfig.json b/playground/vitest-cypress/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/vitest-cypress/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/vitest-cypress/package.json b/playground/vitest-cypress/package.json new file mode 100644 index 000000000..9aae6fe3d --- /dev/null +++ b/playground/vitest-cypress/package.json @@ -0,0 +1,26 @@ +{ + "name": "vitest-cypress", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "start-server-and-test": "^2.0.3", + "vite": "^5.0.11", + "vitest": "^1.2.2" + } +} diff --git a/playground/vitest-cypress/public/favicon.ico b/playground/vitest-cypress/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/vitest-cypress/src/App.vue b/playground/vitest-cypress/src/App.vue new file mode 100644 index 000000000..b6f965e35 --- /dev/null +++ b/playground/vitest-cypress/src/App.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/playground/vitest-cypress/src/assets/logo.svg b/playground/vitest-cypress/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/vitest-cypress/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/vitest-cypress/src/assets/main.css b/playground/vitest-cypress/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/vitest-cypress/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/vitest-cypress/src/components/__tests__/HelloWorld.spec.js b/playground/vitest-cypress/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/vitest-cypress/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/vitest-cypress/src/main.js b/playground/vitest-cypress/src/main.js new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/vitest-cypress/src/main.js @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/vitest-cypress/vite.config.js b/playground/vitest-cypress/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/vitest-cypress/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/vitest-cypress/vitest.config.js b/playground/vitest-cypress/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/vitest-cypress/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/vitest-nightwatch/.gitignore b/playground/vitest-nightwatch/.gitignore new file mode 100644 index 000000000..0b938f131 --- /dev/null +++ b/playground/vitest-nightwatch/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +logs/ +tests_output/ diff --git a/playground/vitest-nightwatch/.vscode/extensions.json b/playground/vitest-nightwatch/.vscode/extensions.json new file mode 100644 index 000000000..dd9668a5c --- /dev/null +++ b/playground/vitest-nightwatch/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["browserstackcom.nightwatch"] +} diff --git a/playground/vitest-nightwatch/README.md b/playground/vitest-nightwatch/README.md new file mode 100644 index 000000000..626767450 --- /dev/null +++ b/playground/vitest-nightwatch/README.md @@ -0,0 +1,58 @@ +# vitest-nightwatch + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Nightwatch](https://nightwatchjs.org/) + +```sh +# When using CI, the project must be built first. +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chrome +pnpm test:e2e --env chrome +# Runs the tests of a specific file +pnpm test:e2e tests/e2e/example.js +# Runs the tests in debug mode +pnpm test:e2e --debug +``` + +### Run Headed Component Tests with [Nightwatch Component Testing](https://nightwatchjs.org/guide/component-testing/introduction.html) + +```sh +pnpm test:unit +pnpm test:unit -- --headless # for headless testing +``` diff --git a/playground/vitest-nightwatch/index.html b/playground/vitest-nightwatch/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/vitest-nightwatch/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/vitest-nightwatch/jsconfig.json b/playground/vitest-nightwatch/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/vitest-nightwatch/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/vitest-nightwatch/nightwatch.conf.cjs b/playground/vitest-nightwatch/nightwatch.conf.cjs new file mode 100644 index 000000000..542647e5e --- /dev/null +++ b/playground/vitest-nightwatch/nightwatch.conf.cjs @@ -0,0 +1,153 @@ +// +// Refer to the online docs for more details: +// https://nightwatchjs.org/guide/configuration/nightwatch-configuration-file.html +// +// _ _ _ _ _ _ _ +// | \ | |(_) | | | | | | | | +// | \| | _ __ _ | |__ | |_ __ __ __ _ | |_ ___ | |__ +// | . ` || | / _` || '_ \ | __|\ \ /\ / / / _` || __| / __|| '_ \ +// | |\ || || (_| || | | || |_ \ V V / | (_| || |_ | (__ | | | | +// \_| \_/|_| \__, ||_| |_| \__| \_/\_/ \__,_| \__| \___||_| |_| +// __/ | +// |___/ +// + +module.exports = { + // An array of folders (excluding subfolders) where your tests are located; + // if this is not specified, the test source must be passed as the second argument to the test runner. + src_folders: [], + + // See https://nightwatchjs.org/guide/concepts/page-object-model.html + page_objects_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-commands.html + custom_commands_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-custom-assertions.html + custom_assertions_path: [], + + // See https://nightwatchjs.org/guide/extending-nightwatch/adding-plugins.html + plugins: ['@nightwatch/vue'], + + // See https://nightwatchjs.org/guide/concepts/test-globals.html#external-test-globals + globals_path: '', + + vite_dev_server: { + start_vite: true, + port: process.env.CI ? 4173 : 5173 + }, + + webdriver: {}, + + test_workers: { + enabled: true, + workers: 'auto' + }, + + test_settings: { + default: { + disable_error_log: false, + launch_url: `http://localhost:${process.env.CI ? '4173' : '5173'}`, + + screenshots: { + enabled: false, + path: 'screens', + on_failure: true + }, + + desiredCapabilities: { + browserName: 'firefox' + }, + + webdriver: { + start_process: true, + server_path: '' + } + }, + + safari: { + desiredCapabilities: { + browserName: 'safari', + alwaysMatch: { + acceptInsecureCerts: false + } + }, + webdriver: { + start_process: true, + server_path: '' + } + }, + + firefox: { + desiredCapabilities: { + browserName: 'firefox', + alwaysMatch: { + acceptInsecureCerts: true, + 'moz:firefoxOptions': { + args: [ + // '-headless', + // '-verbose' + ] + } + } + }, + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // very verbose geckodriver logs + // '-vv' + ] + } + }, + + chrome: { + desiredCapabilities: { + browserName: 'chrome', + 'goog:chromeOptions': { + // More info on Chromedriver: https://sites.google.com/a/chromium.org/chromedriver/ + // + // w3c:false tells Chromedriver to run using the legacy JSONWire protocol (not required in Chrome 78) + w3c: true, + args: [ + //'--no-sandbox', + //'--ignore-certificate-errors', + //'--allow-insecure-localhost', + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + server_path: '', + cli_args: [ + // --verbose + ] + } + }, + + edge: { + desiredCapabilities: { + browserName: 'MicrosoftEdge', + 'ms:edgeOptions': { + w3c: true, + // More info on EdgeDriver: https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/capabilities-edge-options + args: [ + //'--headless' + ] + } + }, + + webdriver: { + start_process: true, + // Download msedgedriver from https://docs.microsoft.com/en-us/microsoft-edge/webdriver-chromium/ + // and set the location below: + server_path: '', + cli_args: [ + // --verbose + ] + } + } + } +} diff --git a/playground/vitest-nightwatch/package.json b/playground/vitest-nightwatch/package.json new file mode 100644 index 000000000..24879046f --- /dev/null +++ b/playground/vitest-nightwatch/package.json @@ -0,0 +1,29 @@ +{ + "name": "vitest-nightwatch", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "nightwatch tests/e2e/*" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@nightwatch/vue": "^3.1.0", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "chromedriver": "^121.0.0", + "geckodriver": "^4.3.2", + "jsdom": "^24.0.0", + "nightwatch": "^3.4.0", + "ts-node": "^10.9.2", + "vite": "^5.0.11", + "vite-plugin-nightwatch": "^0.4.6", + "vitest": "^1.2.2" + } +} diff --git a/playground/vitest-nightwatch/public/favicon.ico b/playground/vitest-nightwatch/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/vitest-nightwatch/src/App.vue b/playground/vitest-nightwatch/src/App.vue new file mode 100644 index 000000000..b6f965e35 --- /dev/null +++ b/playground/vitest-nightwatch/src/App.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/playground/vitest-nightwatch/src/assets/logo.svg b/playground/vitest-nightwatch/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/vitest-nightwatch/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/vitest-nightwatch/src/assets/main.css b/playground/vitest-nightwatch/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/vitest-nightwatch/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/vitest-nightwatch/src/components/__tests__/HelloWorld.spec.js b/playground/vitest-nightwatch/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/vitest-nightwatch/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/vitest-nightwatch/src/main.js b/playground/vitest-nightwatch/src/main.js new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/vitest-nightwatch/src/main.js @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/vitest-nightwatch/tests/e2e/example.js b/playground/vitest-nightwatch/tests/e2e/example.js new file mode 100644 index 000000000..43be3fce1 --- /dev/null +++ b/playground/vitest-nightwatch/tests/e2e/example.js @@ -0,0 +1,11 @@ +describe('My First Test', function () { + before((browser) => { + browser.init() + }) + + it('visits the app root url', function () { + browser.assert.textContains('.green', 'You did it!') + }) + + after((browser) => browser.end()) +}) diff --git a/playground/vitest-nightwatch/vite.config.js b/playground/vitest-nightwatch/vite.config.js new file mode 100644 index 000000000..be3cb9c57 --- /dev/null +++ b/playground/vitest-nightwatch/vite.config.js @@ -0,0 +1,18 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import nightwatchPlugin from 'vite-plugin-nightwatch' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + nightwatchPlugin(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/vitest-nightwatch/vitest.config.js b/playground/vitest-nightwatch/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/vitest-nightwatch/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/vitest-playwright/.gitignore b/playground/vitest-playwright/.gitignore new file mode 100644 index 000000000..aef72d03c --- /dev/null +++ b/playground/vitest-playwright/.gitignore @@ -0,0 +1,33 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +test-results/ +playwright-report/ diff --git a/playground/vitest-playwright/.vscode/extensions.json b/playground/vitest-playwright/.vscode/extensions.json new file mode 100644 index 000000000..7b3f8bdae --- /dev/null +++ b/playground/vitest-playwright/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["ms-playwright.playwright"] +} diff --git a/playground/vitest-playwright/README.md b/playground/vitest-playwright/README.md new file mode 100644 index 000000000..ba4197ffa --- /dev/null +++ b/playground/vitest-playwright/README.md @@ -0,0 +1,54 @@ +# vitest-playwright + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Playwright](https://playwright.dev) + +```sh +# Install browsers for the first run +npx playwright install + +# When testing on CI, must build the project first +pnpm build + +# Runs the end-to-end tests +pnpm test:e2e +# Runs the tests only on Chromium +pnpm test:e2e --project=chromium +# Runs the tests of a specific file +pnpm test:e2e tests/example.spec.ts +# Runs the tests in debug mode +pnpm test:e2e --debug +``` diff --git a/playground/vitest-playwright/e2e/vue.spec.js b/playground/vitest-playwright/e2e/vue.spec.js new file mode 100644 index 000000000..3e5a3d02d --- /dev/null +++ b/playground/vitest-playwright/e2e/vue.spec.js @@ -0,0 +1,8 @@ +import { test, expect } from '@playwright/test'; + +// See here how to get started: +// https://playwright.dev/docs/intro +test('visits the app root url', async ({ page }) => { + await page.goto('/'); + await expect(page.locator('div.greetings > h1')).toHaveText('You did it!'); +}) diff --git a/playground/vitest-playwright/index.html b/playground/vitest-playwright/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/vitest-playwright/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/vitest-playwright/jsconfig.json b/playground/vitest-playwright/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/vitest-playwright/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/vitest-playwright/package.json b/playground/vitest-playwright/package.json new file mode 100644 index 000000000..1e3ea03d5 --- /dev/null +++ b/playground/vitest-playwright/package.json @@ -0,0 +1,24 @@ +{ + "name": "vitest-playwright", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "playwright test" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@playwright/test": "^1.41.2", + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "jsdom": "^24.0.0", + "vite": "^5.0.11", + "vitest": "^1.2.2" + } +} diff --git a/playground/vitest-playwright/playwright.config.js b/playground/vitest-playwright/playwright.config.js new file mode 100644 index 000000000..92075cc1b --- /dev/null +++ b/playground/vitest-playwright/playwright.config.js @@ -0,0 +1,110 @@ +import process from 'node:process' +import { defineConfig, devices } from '@playwright/test' + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: './e2e', + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000 + }, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: 'html', + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + baseURL: 'http://localhost:5173', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: 'on-first-retry', + + /* Only on CI systems run the tests headless */ + headless: !!process.env.CI + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'] + } + }, + { + name: 'firefox', + use: { + ...devices['Desktop Firefox'] + } + }, + { + name: 'webkit', + use: { + ...devices['Desktop Safari'] + } + } + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + webServer: { + /** + * Use the dev server by default for faster feedback loop. + * Use the preview server on CI for more realistic testing. + * Playwright will re-use the local server if there is already a dev-server running. + */ + command: process.env.CI ? 'vite preview --port 5173' : 'vite dev', + port: 5173, + reuseExistingServer: !process.env.CI + } +}) diff --git a/playground/vitest-playwright/public/favicon.ico b/playground/vitest-playwright/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/vitest-playwright/src/App.vue b/playground/vitest-playwright/src/App.vue new file mode 100644 index 000000000..b6f965e35 --- /dev/null +++ b/playground/vitest-playwright/src/App.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/playground/vitest-playwright/src/assets/logo.svg b/playground/vitest-playwright/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/vitest-playwright/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/vitest-playwright/src/assets/main.css b/playground/vitest-playwright/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/vitest-playwright/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/vitest-playwright/src/components/__tests__/HelloWorld.spec.js b/playground/vitest-playwright/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/vitest-playwright/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/vitest-playwright/src/main.js b/playground/vitest-playwright/src/main.js new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/vitest-playwright/src/main.js @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/vitest-playwright/vite.config.js b/playground/vitest-playwright/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/vitest-playwright/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/vitest-playwright/vitest.config.js b/playground/vitest-playwright/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/vitest-playwright/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/vitest/.gitignore b/playground/vitest/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/vitest/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/vitest/README.md b/playground/vitest/README.md new file mode 100644 index 000000000..48871df54 --- /dev/null +++ b/playground/vitest/README.md @@ -0,0 +1,35 @@ +# vitest + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` diff --git a/playground/vitest/index.html b/playground/vitest/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/vitest/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/vitest/jsconfig.json b/playground/vitest/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/vitest/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/vitest/package.json b/playground/vitest/package.json new file mode 100644 index 000000000..c1370e1e8 --- /dev/null +++ b/playground/vitest/package.json @@ -0,0 +1,22 @@ +{ + "name": "vitest", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "jsdom": "^24.0.0", + "vite": "^5.0.11", + "vitest": "^1.2.2" + } +} diff --git a/playground/vitest/public/favicon.ico b/playground/vitest/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/vitest/src/App.vue b/playground/vitest/src/App.vue new file mode 100644 index 000000000..b6f965e35 --- /dev/null +++ b/playground/vitest/src/App.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/playground/vitest/src/assets/logo.svg b/playground/vitest/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/vitest/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/vitest/src/assets/main.css b/playground/vitest/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/vitest/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/vitest/src/components/__tests__/HelloWorld.spec.js b/playground/vitest/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/vitest/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/vitest/src/main.js b/playground/vitest/src/main.js new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/vitest/src/main.js @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/vitest/vite.config.js b/playground/vitest/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/vitest/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/vitest/vitest.config.js b/playground/vitest/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/vitest/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/playground/with-tests/.gitignore b/playground/with-tests/.gitignore new file mode 100644 index 000000000..8ee54e8d3 --- /dev/null +++ b/playground/with-tests/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/playground/with-tests/README.md b/playground/with-tests/README.md new file mode 100644 index 000000000..3f1c26fbf --- /dev/null +++ b/playground/with-tests/README.md @@ -0,0 +1,51 @@ +# with-tests + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin). + +## Customize configuration + +See [Vite Configuration Reference](https://vitejs.dev/config/). + +## Project Setup + +```sh +pnpm install +``` + +### Compile and Hot-Reload for Development + +```sh +pnpm dev +``` + +### Compile and Minify for Production + +```sh +pnpm build +``` + +### Run Unit Tests with [Vitest](https://vitest.dev/) + +```sh +pnpm test:unit +``` + +### Run End-to-End Tests with [Cypress](https://www.cypress.io/) + +```sh +pnpm test:e2e:dev +``` + +This runs the end-to-end tests against the Vite development server. +It is much faster than the production build. + +But it's still recommended to test the production build with `test:e2e` before deploying (e.g. in CI environments): + +```sh +pnpm build +pnpm test:e2e +``` diff --git a/playground/with-tests/cypress.config.js b/playground/with-tests/cypress.config.js new file mode 100644 index 000000000..0f66080fd --- /dev/null +++ b/playground/with-tests/cypress.config.js @@ -0,0 +1,8 @@ +import { defineConfig } from 'cypress' + +export default defineConfig({ + e2e: { + specPattern: 'cypress/e2e/**/*.{cy,spec}.{js,jsx,ts,tsx}', + baseUrl: 'http://localhost:4173' + } +}) diff --git a/playground/with-tests/cypress/e2e/example.cy.js b/playground/with-tests/cypress/e2e/example.cy.js new file mode 100644 index 000000000..7554c35d8 --- /dev/null +++ b/playground/with-tests/cypress/e2e/example.cy.js @@ -0,0 +1,8 @@ +// https://on.cypress.io/api + +describe('My First Test', () => { + it('visits the app root url', () => { + cy.visit('/') + cy.contains('h1', 'You did it!') + }) +}) diff --git a/playground/with-tests/cypress/e2e/jsconfig.json b/playground/with-tests/cypress/e2e/jsconfig.json new file mode 100644 index 000000000..c790a70d6 --- /dev/null +++ b/playground/with-tests/cypress/e2e/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "target": "es5", + "lib": ["es5", "dom"], + "types": ["cypress"] + }, + "include": ["./**/*", "../support/**/*"] +} diff --git a/playground/with-tests/cypress/fixtures/example.json b/playground/with-tests/cypress/fixtures/example.json new file mode 100644 index 000000000..02e425437 --- /dev/null +++ b/playground/with-tests/cypress/fixtures/example.json @@ -0,0 +1,5 @@ +{ + "name": "Using fixtures to represent data", + "email": "hello@cypress.io", + "body": "Fixtures are a great way to mock data for responses to routes" +} diff --git a/playground/with-tests/cypress/support/commands.js b/playground/with-tests/cypress/support/commands.js new file mode 100644 index 000000000..119ab03f7 --- /dev/null +++ b/playground/with-tests/cypress/support/commands.js @@ -0,0 +1,25 @@ +// *********************************************** +// This example commands.js shows you how to +// create various custom commands and overwrite +// existing commands. +// +// For more comprehensive examples of custom +// commands please read more here: +// https://on.cypress.io/custom-commands +// *********************************************** +// +// +// -- This is a parent command -- +// Cypress.Commands.add('login', (email, password) => { ... }) +// +// +// -- This is a child command -- +// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... }) +// +// +// -- This is a dual command -- +// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... }) +// +// +// -- This will overwrite an existing command -- +// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... }) diff --git a/playground/with-tests/cypress/support/e2e.js b/playground/with-tests/cypress/support/e2e.js new file mode 100644 index 000000000..d68db96df --- /dev/null +++ b/playground/with-tests/cypress/support/e2e.js @@ -0,0 +1,20 @@ +// *********************************************************** +// This example support/index.js is processed and +// loaded automatically before your test files. +// +// This is a great place to put global configuration and +// behavior that modifies Cypress. +// +// You can change the location of this file or turn off +// automatically serving support files with the +// 'supportFile' configuration option. +// +// You can read more here: +// https://on.cypress.io/configuration +// *********************************************************** + +// Import commands.js using ES2015 syntax: +import './commands' + +// Alternatively you can use CommonJS syntax: +// require('./commands') diff --git a/playground/with-tests/index.html b/playground/with-tests/index.html new file mode 100644 index 000000000..99f583aa2 --- /dev/null +++ b/playground/with-tests/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite App + + +
+ + + diff --git a/playground/with-tests/jsconfig.json b/playground/with-tests/jsconfig.json new file mode 100644 index 000000000..5a1f2d222 --- /dev/null +++ b/playground/with-tests/jsconfig.json @@ -0,0 +1,8 @@ +{ + "compilerOptions": { + "paths": { + "@/*": ["./src/*"] + } + }, + "exclude": ["node_modules", "dist"] +} diff --git a/playground/with-tests/package.json b/playground/with-tests/package.json new file mode 100644 index 000000000..2aaac0df4 --- /dev/null +++ b/playground/with-tests/package.json @@ -0,0 +1,26 @@ +{ + "name": "with-tests", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview", + "test:unit": "vitest", + "test:e2e": "start-server-and-test preview http://localhost:4173 'cypress run --e2e'", + "test:e2e:dev": "start-server-and-test 'vite dev --port 4173' http://localhost:4173 'cypress open --e2e'" + }, + "dependencies": { + "vue": "^3.4.15" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "@vue/test-utils": "^2.4.4", + "cypress": "^13.6.4", + "jsdom": "^24.0.0", + "start-server-and-test": "^2.0.3", + "vite": "^5.0.11", + "vitest": "^1.2.2" + } +} diff --git a/playground/with-tests/public/favicon.ico b/playground/with-tests/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..df36fcfb72584e00488330b560ebcf34a41c64c2 GIT binary patch literal 4286 zcmds*O-Phc6o&64GDVCEQHxsW(p4>LW*W<827=Unuo8sGpRux(DN@jWP-e29Wl%wj zY84_aq9}^Am9-cWTD5GGEo#+5Fi2wX_P*bo+xO!)p*7B;iKlbFd(U~_d(U?#hLj56 zPhFkj-|A6~Qk#@g^#D^U0XT1cu=c-vu1+SElX9NR;kzAUV(q0|dl0|%h|dI$%VICy zJnu2^L*Te9JrJMGh%-P79CL0}dq92RGU6gI{v2~|)p}sG5x0U*z<8U;Ij*hB9z?ei z@g6Xq-pDoPl=MANPiR7%172VA%r)kevtV-_5H*QJKFmd;8yA$98zCxBZYXTNZ#QFk2(TX0;Y2dt&WitL#$96|gJY=3xX zpCoi|YNzgO3R`f@IiEeSmKrPSf#h#Qd<$%Ej^RIeeYfsxhPMOG`S`Pz8q``=511zm zAm)MX5AV^5xIWPyEu7u>qYs?pn$I4nL9J!=K=SGlKLXpE<5x+2cDTXq?brj?n6sp= zphe9;_JHf40^9~}9i08r{XM$7HB!`{Ys~TK0kx<}ZQng`UPvH*11|q7&l9?@FQz;8 zx!=3<4seY*%=OlbCbcae?5^V_}*K>Uo6ZWV8mTyE^B=DKy7-sdLYkR5Z?paTgK-zyIkKjIcpyO z{+uIt&YSa_$QnN_@t~L014dyK(fOOo+W*MIxbA6Ndgr=Y!f#Tokqv}n<7-9qfHkc3 z=>a|HWqcX8fzQCT=dqVbogRq!-S>H%yA{1w#2Pn;=e>JiEj7Hl;zdt-2f+j2%DeVD zsW0Ab)ZK@0cIW%W7z}H{&~yGhn~D;aiP4=;m-HCo`BEI+Kd6 z={Xwx{TKxD#iCLfl2vQGDitKtN>z|-AdCN|$jTFDg0m3O`WLD4_s#$S literal 0 HcmV?d00001 diff --git a/playground/with-tests/src/App.vue b/playground/with-tests/src/App.vue new file mode 100644 index 000000000..b6f965e35 --- /dev/null +++ b/playground/with-tests/src/App.vue @@ -0,0 +1,9 @@ + + + + + diff --git a/playground/with-tests/src/assets/logo.svg b/playground/with-tests/src/assets/logo.svg new file mode 100644 index 000000000..756566035 --- /dev/null +++ b/playground/with-tests/src/assets/logo.svg @@ -0,0 +1 @@ + diff --git a/playground/with-tests/src/assets/main.css b/playground/with-tests/src/assets/main.css new file mode 100644 index 000000000..5aadc6ceb --- /dev/null +++ b/playground/with-tests/src/assets/main.css @@ -0,0 +1,6 @@ +html, body, #app { + width: 100%; + height: 100%; + padding: 0; + margin: 0; +} diff --git a/playground/with-tests/src/components/__tests__/HelloWorld.spec.js b/playground/with-tests/src/components/__tests__/HelloWorld.spec.js new file mode 100644 index 000000000..253320200 --- /dev/null +++ b/playground/with-tests/src/components/__tests__/HelloWorld.spec.js @@ -0,0 +1,11 @@ +import { describe, it, expect } from 'vitest' + +import { mount } from '@vue/test-utils' +import HelloWorld from '../HelloWorld.vue' + +describe('HelloWorld', () => { + it('renders properly', () => { + const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } }) + expect(wrapper.text()).toContain('Hello Vitest') + }) +}) diff --git a/playground/with-tests/src/main.js b/playground/with-tests/src/main.js new file mode 100644 index 000000000..0ac3a5ff0 --- /dev/null +++ b/playground/with-tests/src/main.js @@ -0,0 +1,6 @@ +import './assets/main.css' + +import { createApp } from 'vue' +import App from './App.vue' + +createApp(App).mount('#app') diff --git a/playground/with-tests/vite.config.js b/playground/with-tests/vite.config.js new file mode 100644 index 000000000..5c45e1d9b --- /dev/null +++ b/playground/with-tests/vite.config.js @@ -0,0 +1,16 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } + } +}) diff --git a/playground/with-tests/vitest.config.js b/playground/with-tests/vitest.config.js new file mode 100644 index 000000000..10067d578 --- /dev/null +++ b/playground/with-tests/vitest.config.js @@ -0,0 +1,14 @@ +import { fileURLToPath } from 'node:url' +import { mergeConfig, defineConfig, configDefaults } from 'vitest/config' +import viteConfig from './vite.config' + +export default mergeConfig( + viteConfig, + defineConfig({ + test: { + environment: 'jsdom', + exclude: [...configDefaults.exclude, 'e2e/*'], + root: fileURLToPath(new URL('./', import.meta.url)) + } + }) +) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 372b7b7dd..ae3a34979 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -72,6 +72,9 @@ importers: '@vitejs/plugin-vue': specifier: ^5.0.3 version: 5.0.3(vite@5.0.11)(vue@3.4.15) + husky: + specifier: ^9.0.11 + version: 9.0.11 vite: specifier: ^5.0.11 version: 5.0.11(@types/node@20.11.16) @@ -1212,6 +1215,7 @@ packages: resolution: {integrity: sha512-OrEyIfpxSsMal44JpEVx9AEcGpdBQG1ZuWISAanaQTSMeStBW+oHWwOkoqR54bw3x8heP8gBOyoJiGg+fLY8qQ==} cpu: [arm64] os: [linux] + libc: [glibc] requiresBuild: true dev: true optional: true @@ -1220,6 +1224,7 @@ packages: resolution: {integrity: sha512-1H7wBbQuE6igQdxMSTjtFfD+DGAudcYWhp106z/9zBA8OQhsJRnemO4XGavdzHpGhRtRxbgmUGdO3YQgrWf2RA==} cpu: [arm64] os: [linux] + libc: [musl] requiresBuild: true dev: true optional: true @@ -1228,6 +1233,7 @@ packages: resolution: {integrity: sha512-FVyFI13tXw5aE65sZdBpNjPVIi4Q5mARnL/39UIkxvSgRAIqCo5sCpCELk0JtXHGee2owZz5aNLbWNfBHzr71Q==} cpu: [x64] os: [linux] + libc: [glibc] requiresBuild: true dev: true optional: true @@ -1236,6 +1242,7 @@ packages: resolution: {integrity: sha512-eBPYl2sLpH/o8qbSz6vPwWlDyThnQjJfcDOGFbNjmjb44XKC1F5dQfakOsADRVrXCNzM6ZsSIPDG5dc6HHLNFg==} cpu: [x64] os: [linux] + libc: [musl] requiresBuild: true dev: true optional: true @@ -3705,6 +3712,12 @@ packages: hasBin: true dev: true + /husky@9.0.11: + resolution: {integrity: sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==} + engines: {node: '>=18'} + hasBin: true + dev: true + /iconv-lite@0.6.3: resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} engines: {node: '>=0.10.0'} diff --git a/scripts/LICENSE b/scripts/LICENSE new file mode 100644 index 000000000..7e3f1fdeb --- /dev/null +++ b/scripts/LICENSE @@ -0,0 +1,33 @@ +# create-vue core license + +create-vue is released under the MIT license: + +MIT License + +Copyright (c) 2021-present vuejs + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +## Licenses of bundled dependencies + +The published create-vue artifact additionally contains code with the following licenses: + + +## Bundled dependencies + diff --git a/template/base/.eslintignore b/template/base/.eslintignore new file mode 100644 index 000000000..e2e5c4276 --- /dev/null +++ b/template/base/.eslintignore @@ -0,0 +1,5 @@ +/node_modules/ +/src/mock/ +/src/assets/ +./package-lock.json +useless-*.* diff --git a/template/base/.eslintrc.cjs b/template/base/.eslintrc.cjs new file mode 100644 index 000000000..0e3c48b7c --- /dev/null +++ b/template/base/.eslintrc.cjs @@ -0,0 +1,119 @@ +// @ts-check +require('@rushstack/eslint-patch/modern-module-resolution') +/** + * ESLint Configuration File + * + * Docs: https://eslint.org/docs/user-guide/configuring + * @type {import('eslint').Config} + */ +module.exports = { + /** + * Config Root + */ + root: true, + /** + * Custom Rules + */ + rules: { + 'no-console': 'off', + 'no-debugger': 'off', + }, + /** + * Custom Groups + */ + overrides: [ + { + files: ['./*.config.js', './*rc.js', '**/scripts/**/*.js'], + env: { + node: true, + }, + parserOptions: { + sourceType: 'module', + }, + parser: '@babel/eslint-parser', + rules: { + 'no-unused-vars': 'off', + 'no-prototype-builtins': 'off', + }, + extends: ['eslint:recommended', 'plugin:prettier/recommended'], + }, + { + files: ['./public/**/*.js'], + env: { + browser: true, + }, + parserOptions: { + sourceType: 'module', + }, + rules: { + 'no-unused-vars': 'off', + 'no-prototype-builtins': 'off', + }, + extends: ['eslint:recommended', 'plugin:prettier/recommended'], + }, + { + files: ['*.js', '*.jsx'], + env: { + es2020: true, + node: true, + browser: true, + }, + parserOptions: { + sourceType: 'module', + }, + parser: '@babel/eslint-parser', + rules: { + 'no-unused-vars': 'warn', + 'no-prototype-builtins': 'off', + }, + extends: ['eslint:recommended', 'plugin:prettier/recommended'], + }, + { + files: ['*.ts', '*.tsx'], + env: { + es2020: true, + browser: true, + }, + parser: '@typescript-eslint/parser', + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/eslint-recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + rules: { + '@typescript-eslint/no-unused-vars': 'warn', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/no-explicit-any': 'off', + 'no-prototype-builtins': 'off', + }, + }, + { + files: ['*.vue'], + env: { + es2020: true, + browser: true, + node: true, + }, + parser: 'vue-eslint-parser', + parserOptions: { + sourceType: 'module', + ecmaVersion: 'latest', + }, + extends: [ + 'eslint:recommended', + 'plugin:prettier/recommended', + 'plugin:vue/vue3-essential', + '@vue/eslint-config-typescript', + '@vue/eslint-config-prettier/skip-formatting' + ], + rules: { + 'no-unreachable': 'warn', + 'no-debugger': 'warn', + 'no-prototype-builtins': 'off', + 'no-unused-vars': 'warn', + 'vue/multi-word-component-names': 'off', + }, + }, + ], +}; diff --git a/template/base/.gitignore b/template/base/.gitignore new file mode 100644 index 000000000..9dc061034 --- /dev/null +++ b/template/base/.gitignore @@ -0,0 +1,36 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +./package-lock.json +/node_modules/ +/dist/ +/.idea/ +/.husky/ diff --git a/template/base/.prettierrc.json b/template/base/.prettierrc.json new file mode 100644 index 000000000..4fa3f78bd --- /dev/null +++ b/template/base/.prettierrc.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": true, + "arrowParens": "always", + "singleQuote": true, + "endOfLine": "auto", + "printWidth": 120, + "tabWidth": 4 +} diff --git a/template/base/package.json b/template/base/package.json index 89f2e503a..ba8411bb4 100644 --- a/template/base/package.json +++ b/template/base/package.json @@ -1,16 +1,21 @@ { - "private": true, - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview" - }, - "dependencies": { - "vue": "^3.4.15" - }, - "devDependencies": { - "@vitejs/plugin-vue": "^5.0.3", - "vite": "^5.0.11" - } + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "cross-env NODE_ENV=prod vite build", + "preview": "vite preview", + "prepare": "husky" + }, + "dependencies": { + "vue": "^3.4.15", + "lodash": "^4.17.21", + "axios": "^1.6.7" + }, + "devDependencies": { + "@vitejs/plugin-vue": "^5.0.3", + "vite": "^5.0.11", + "husky": "^9.0.11", + "cross-env": "^7.0.3" + } } diff --git a/template/base/public/config.js b/template/base/public/config.js new file mode 100644 index 000000000..e7085a29e --- /dev/null +++ b/template/base/public/config.js @@ -0,0 +1,23 @@ +(function () { + const CONFIG_NAME = 'CUSTOM_PUBLIC_CONFIG'; + if (!isObject(window[CONFIG_NAME])) window[CONFIG_NAME] = {}; + const DEFAULT_CONFIG = {}; + // 逐层合并配置的全局变量 + window[CONFIG_NAME] = DEFAULT_CONFIG; + objectAssignRecursively(DEFAULT_CONFIG, window[CONFIG_NAME]); + + function objectAssignRecursively(targetObj, originObj) { + let newObj = Object.assign({}, targetObj, originObj); + for (let [k, v] of Object.entries(originObj)) { + let targetValue = targetObj[k]; + if (isObject(v) && isObject(targetValue)) { + newObj[k] = objectAssignRecursively(targetValue, v); + } + } + return newObj; + } + + function isObject(value) { + return Object.prototype.toString.apply(value) === '[object Object]'; + } +})(); diff --git a/template/base/src/api/apiIndex.js b/template/base/src/api/apiIndex.js new file mode 100644 index 000000000..29a92b0c8 --- /dev/null +++ b/template/base/src/api/apiIndex.js @@ -0,0 +1,13 @@ +import Qs from 'querystring'; +import { HttpRequest } from '@/libs/custom_axios'; +import config from '@/config/configIndex'; +import axios from 'axios'; + +let [backend_api] = + process.env.NODE_ENV === 'development' ? [config.baseUrl.backend_dev] : [config.baseUrl.backend_pro]; + +export const axios_backend_api = new HttpRequest(backend_api); + +let baseUrl = backend_api; +if (baseUrl[baseUrl.length - 1] == '/') baseUrl = baseUrl.slice(0, -1); +export const prefixBackendBaseUrl = baseUrl; diff --git a/template/base/src/api/apisTest.js b/template/base/src/api/apisTest.js new file mode 100644 index 000000000..1f8fff0ad --- /dev/null +++ b/template/base/src/api/apisTest.js @@ -0,0 +1,12 @@ +import { axios_backend_api } from '@/api/apiIndex'; + +/** + * 上报案件 + */ +export const apiUploadCase = (data) => { + return axios_backend_api.request({ + url: '/api/si/scdld/upload', + method: 'post', + data, + }); +}; diff --git a/template/base/src/config/configIndex.js b/template/base/src/config/configIndex.js new file mode 100644 index 000000000..7de1eac3a --- /dev/null +++ b/template/base/src/config/configIndex.js @@ -0,0 +1,21 @@ +const BACKEND = import.meta.env.BACKEND; + +const Qs = require('querystring'); +const public_config = window['CUSTOM_PUBLIC_CONFIG']; +const url = window.location.href + ''; +const paramsObj = Qs.decode(url.slice(url.indexOf('?') + 1)); + +const local_config = { + baseUrl: { + /*dev*/ + backend_dev: '//localhost:8088', + + /*pro*/ + backend_pro: BACKEND + '/api/test/', + }, + mockMode: !!1, +}; +const baseUrl_config = Object.assign({}, local_config.baseUrl, public_config.baseUrl); +let merge_config = Object.assign({}, local_config, public_config); +merge_config.baseUrl = baseUrl_config; +export default merge_config; diff --git a/template/base/src/libs/custom_axios.js b/template/base/src/libs/custom_axios.js new file mode 100644 index 000000000..82a593391 --- /dev/null +++ b/template/base/src/libs/custom_axios.js @@ -0,0 +1,28 @@ +import axios from 'axios'; + +class HttpRequest { + constructor(baseUrl = '') { + this.baseUrl = baseUrl; + this.queue = {}; + } + getInsideConfig() { + return { + baseURL: this.baseUrl, + headers: { + // + }, + }; + } + destroy(url) { + delete this.queue[url]; + /*if (!Object.keys(this.queue).length) { + return; + }*/ + } + request(options) { + const instance = axios.create(); + options = Object.assign(this.getInsideConfig(), options); + return instance(options); + } +} +export default HttpRequest; diff --git a/template/base/vite.config.js.ejs b/template/base/vite.config.js.ejs index c3e65d219..c418ba7c1 100644 --- a/template/base/vite.config.js.ejs +++ b/template/base/vite.config.js.ejs @@ -1,20 +1,25 @@ import { fileURLToPath, URL } from 'node:url' -import { defineConfig } from 'vite' +import { defineConfig, loadEnv } from 'vite' <%_ for (const { importer } of plugins) { _%> <%- importer %> <%_ } _%> // https://vitejs.dev/config/ -export default defineConfig({ - plugins: [ - <%_ for (const { initializer } of plugins) { _%> - <%- initializer _%>, - <%_ } _%> - ], - resolve: { - alias: { - '@': fileURLToPath(new URL('./src', import.meta.url)) +export default ({ mode }) => { + // import.meta.env.VITE_NAME available here with: process.env.VITE_NAME + const env = loadEnv(mode, process.cwd()); + process.env = {...process.env, ...env}; + return defineConfig({ + plugins: [ + <%_ for (const { initializer } of plugins) { _%> + <%- initializer _%>, + <%_ } _%> + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)) + } } - } -}) + }); +} diff --git a/template/code/default/src/App.vue b/template/code/default/src/App.vue index 05664635c..445ce3503 100644 --- a/template/code/default/src/App.vue +++ b/template/code/default/src/App.vue @@ -1,5 +1,10 @@ + diff --git a/template/code/router/src/App.vue b/template/code/router/src/App.vue index 170f14a24..f00379824 100644 --- a/template/code/router/src/App.vue +++ b/template/code/router/src/App.vue @@ -1,4 +1,4 @@ - diff --git a/template/code/typescript-router/src/App.vue b/template/code/typescript-router/src/App.vue index 7905b0516..170f14a24 100644 --- a/template/code/typescript-router/src/App.vue +++ b/template/code/typescript-router/src/App.vue @@ -1,85 +1,9 @@ - + diff --git a/template/code/typescript-router/src/router/index.ts b/template/code/typescript-router/src/router/index.ts index a49ae507f..ff991f568 100644 --- a/template/code/typescript-router/src/router/index.ts +++ b/template/code/typescript-router/src/router/index.ts @@ -1,5 +1,4 @@ import { createRouter, createWebHistory } from 'vue-router' -import HomeView from '../views/HomeView.vue' const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), @@ -7,15 +6,7 @@ const router = createRouter({ { path: '/', name: 'home', - component: HomeView - }, - { - path: '/about', - name: 'about', - // route level code-splitting - // this generates a separate chunk (About.[hash].js) for this route - // which is lazy-loaded when the route is visited. - component: () => import('../views/AboutView.vue') + component: () => import('../views/Home.vue') } ] }) diff --git a/template/code/typescript-router/src/views/Home.vue b/template/code/typescript-router/src/views/Home.vue new file mode 100644 index 000000000..c6aadabc2 --- /dev/null +++ b/template/code/typescript-router/src/views/Home.vue @@ -0,0 +1,5 @@ + + + + + diff --git a/utils/renderEslint.ts b/utils/renderEslint.ts index 99549deaa..243be49ce 100644 --- a/utils/renderEslint.ts +++ b/utils/renderEslint.ts @@ -82,9 +82,15 @@ export default function renderEslint( // write to .eslintrc.cjs, .prettierrc.json, etc. for (const [fileName, content] of Object.entries(files)) { + if (fileName === '.prettierrc.json' || fileName === '.eslintrc.cjs') continue const fullPath = path.resolve(rootDir, fileName) fs.writeFileSync(fullPath, content as string, 'utf-8') } + /*customize part*/ + /*const fullPath = path.resolve(rootDir, '.eslintrc.js')*/ + /*.eslintignore*/ + /*.prettierrc.js*/ + /*fs.writeFileSync(fullPath, content as string, 'utf-8')*/ // update .vscode/extensions.json /*const extensionsJsonPath = path.resolve(rootDir, '.vscode/extensions.json') From acd89044618bc81b8bb1c844cdc770020aca7ff3 Mon Sep 17 00:00:00 2001 From: meatjam <851404658@qq.com> Date: Sat, 17 Feb 2024 22:35:00 +0800 Subject: [PATCH 4/6] update --- index.ts | 12 +++++ pnpm-lock.yaml | 65 +++++++++---------------- template/base/index.html | 1 + template/base/package.json | 3 +- template/base/src/api/apiIndex.js | 10 ++-- template/base/src/config/configIndex.js | 5 +- template/base/src/libs/custom_axios.ts | 31 ++++++++++++ template/base/vite.config.js.ejs | 2 +- 8 files changed, 77 insertions(+), 52 deletions(-) create mode 100644 template/base/src/libs/custom_axios.ts diff --git a/index.ts b/index.ts index 9fc382b9c..a74e5a375 100755 --- a/index.ts +++ b/index.ts @@ -18,6 +18,9 @@ import getCommand from './utils/getCommand' import getLanguage from './utils/getLanguage' import renderEslint from './utils/renderEslint' +const util = require('util') +const exec = util.promisify(require('child_process').exec) + function isValidPackageName(projectName) { return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(projectName) } @@ -566,6 +569,15 @@ async function init() { } console.log(` ${bold(green(getCommand(packageManager, 'dev')))}`) console.log() + const cmds = [ + 'pnpm i' + /*'pnpm exec husky init',*/ + /*'pnpm run prepare'*/ + ] + for (const cmd of cmds) { + const { stdout, stderr } = await exec(`cd ${root} && ${cmd}`) + console.log(stdout, stderr) + } } init().catch((e) => { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ae3a34979..f270c52f7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -65,6 +65,12 @@ importers: template/base: dependencies: + axios: + specifier: ^1.6.7 + version: 1.6.7(debug@4.3.4) + lodash: + specifier: ^4.17.21 + version: 4.17.21 vue: specifier: ^3.4.15 version: 3.4.15(typescript@5.3.3) @@ -72,6 +78,9 @@ importers: '@vitejs/plugin-vue': specifier: ^5.0.3 version: 5.0.3(vite@5.0.11)(vue@3.4.15) + cross-env: + specifier: ^7.0.3 + version: 7.0.3 husky: specifier: ^9.0.11 version: 9.0.11 @@ -1966,7 +1975,6 @@ packages: /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: true /at-least-node@1.0.0: resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} @@ -1991,25 +1999,14 @@ packages: engines: {node: '>=4'} dev: true - /axios@1.6.2(debug@4.3.4): - resolution: {integrity: sha512-7i24Ri4pmDRfJTR7LDBhsOTtcm+9kjX5WiY1X3wIisx6G9So3pfMkEiU7emUBe46oceVImccTEM3k6C5dbVW8A==} + /axios@1.6.7(debug@4.3.4): + resolution: {integrity: sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA==} dependencies: - follow-redirects: 1.15.3(debug@4.3.4) + follow-redirects: 1.15.5(debug@4.3.4) form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: - debug - dev: true - - /axios@1.6.5: - resolution: {integrity: sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==} - dependencies: - follow-redirects: 1.15.5 - form-data: 4.0.0 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - dev: true /b4a@1.6.4: resolution: {integrity: sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==} @@ -2258,7 +2255,7 @@ packages: requiresBuild: true dependencies: '@testim/chrome-version': 1.1.4 - axios: 1.6.5 + axios: 1.6.7(debug@4.3.4) compare-versions: 6.1.0 extract-zip: 2.0.1(supports-color@8.1.1) https-proxy-agent: 5.0.1 @@ -2375,7 +2372,6 @@ packages: engines: {node: '>= 0.8'} dependencies: delayed-stream: 1.0.0 - dev: true /commander@10.0.1: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} @@ -2456,6 +2452,14 @@ packages: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} dev: true + /cross-env@7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true + dependencies: + cross-spawn: 7.0.3 + dev: true + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -2596,7 +2600,6 @@ packages: dependencies: ms: 2.1.2 supports-color: 8.1.1 - dev: true /decamelize@4.0.0: resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} @@ -2686,7 +2689,6 @@ packages: /delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} - dev: true /devtools-protocol@0.0.1025565: resolution: {integrity: sha512-0s5sbGQR/EfYQhd8EpZgphpndsv+CufTlaeUyA6vYXCA0H5kMAsHCS/cHtUFWoKJCO125hpoKicQCfpxRj4oqw==} @@ -3299,8 +3301,8 @@ packages: hasBin: true dev: true - /follow-redirects@1.15.3(debug@4.3.4): - resolution: {integrity: sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==} + /follow-redirects@1.15.5(debug@4.3.4): + resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==} engines: {node: '>=4.0'} peerDependencies: debug: '*' @@ -3309,17 +3311,6 @@ packages: optional: true dependencies: debug: 4.3.4(supports-color@8.1.1) - dev: true - - /follow-redirects@1.15.5: - resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - dev: true /for-each@0.3.3: resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} @@ -3347,7 +3338,6 @@ packages: asynckit: 0.4.0 combined-stream: 1.0.8 mime-types: 2.1.35 - dev: true /formdata-polyfill@4.0.10: resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} @@ -3591,7 +3581,6 @@ packages: /has-flag@4.0.0: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - dev: true /has-property-descriptors@1.0.1: resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} @@ -4348,7 +4337,6 @@ packages: /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true /log-symbols@4.1.0: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} @@ -4450,14 +4438,12 @@ packages: /mime-db@1.52.0: resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} engines: {node: '>= 0.6'} - dev: true /mime-types@2.1.35: resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} engines: {node: '>= 0.6'} dependencies: mime-db: 1.52.0 - dev: true /mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} @@ -4567,7 +4553,6 @@ packages: /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} - dev: true /ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} @@ -5067,7 +5052,6 @@ packages: /proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - dev: true /ps-tree@1.2.0: resolution: {integrity: sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==} @@ -5607,7 +5591,6 @@ packages: engines: {node: '>=10'} dependencies: has-flag: 4.0.0 - dev: true /svg-tags@1.0.0: resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} @@ -6110,7 +6093,7 @@ packages: engines: {node: '>=12.0.0'} hasBin: true dependencies: - axios: 1.6.2(debug@4.3.4) + axios: 1.6.7(debug@4.3.4) joi: 17.11.0 lodash: 4.17.21 minimist: 1.2.8 diff --git a/template/base/index.html b/template/base/index.html index 99f583aa2..a0b0094d7 100644 --- a/template/base/index.html +++ b/template/base/index.html @@ -8,6 +8,7 @@
+ diff --git a/template/base/package.json b/template/base/package.json index ba8411bb4..7c86bcfca 100644 --- a/template/base/package.json +++ b/template/base/package.json @@ -10,7 +10,8 @@ "dependencies": { "vue": "^3.4.15", "lodash": "^4.17.21", - "axios": "^1.6.7" + "axios": "^1.6.7", + "query-string": "^8.2.0" }, "devDependencies": { "@vitejs/plugin-vue": "^5.0.3", diff --git a/template/base/src/api/apiIndex.js b/template/base/src/api/apiIndex.js index 29a92b0c8..47ab65e8f 100644 --- a/template/base/src/api/apiIndex.js +++ b/template/base/src/api/apiIndex.js @@ -1,13 +1,11 @@ -import Qs from 'querystring'; -import { HttpRequest } from '@/libs/custom_axios'; +import HttpRequest from '@/libs/custom_axios'; import config from '@/config/configIndex'; -import axios from 'axios'; +const mode = import.meta.env.MODE; -let [backend_api] = - process.env.NODE_ENV === 'development' ? [config.baseUrl.backend_dev] : [config.baseUrl.backend_pro]; +let [backend_api] = mode === 'development' ? [config.baseUrl.backend_dev] : [config.baseUrl.backend_pro]; export const axios_backend_api = new HttpRequest(backend_api); let baseUrl = backend_api; -if (baseUrl[baseUrl.length - 1] == '/') baseUrl = baseUrl.slice(0, -1); +if (baseUrl[baseUrl.length - 1] === '/') baseUrl = baseUrl.slice(0, -1); export const prefixBackendBaseUrl = baseUrl; diff --git a/template/base/src/config/configIndex.js b/template/base/src/config/configIndex.js index 7de1eac3a..0da22b9f9 100644 --- a/template/base/src/config/configIndex.js +++ b/template/base/src/config/configIndex.js @@ -1,9 +1,8 @@ +import queryString from 'query-string'; const BACKEND = import.meta.env.BACKEND; -const Qs = require('querystring'); const public_config = window['CUSTOM_PUBLIC_CONFIG']; -const url = window.location.href + ''; -const paramsObj = Qs.decode(url.slice(url.indexOf('?') + 1)); +const paramsObj = queryString.parse(window.location.search); const local_config = { baseUrl: { diff --git a/template/base/src/libs/custom_axios.ts b/template/base/src/libs/custom_axios.ts new file mode 100644 index 000000000..f3081d299 --- /dev/null +++ b/template/base/src/libs/custom_axios.ts @@ -0,0 +1,31 @@ +import axios from 'axios'; + +class HttpRequest { + baseUrl: string; + queue: Record; + constructor(baseUrl = '') { + this.baseUrl = baseUrl; + this.queue = {}; + } + getInsideConfig() { + return { + baseURL: this.baseUrl, + headers: { + // + }, + }; + } + destroy(url: string) { + delete this.queue[url]; + /*if (!Object.keys(this.queue).length) { + return; + }*/ + } + + request(options: Record) { + const instance = axios.create(); + options = Object.assign(this.getInsideConfig(), options); + return instance(options); + } +} +export default HttpRequest; diff --git a/template/base/vite.config.js.ejs b/template/base/vite.config.js.ejs index c418ba7c1..670f18ee9 100644 --- a/template/base/vite.config.js.ejs +++ b/template/base/vite.config.js.ejs @@ -6,7 +6,7 @@ import { defineConfig, loadEnv } from 'vite' <%_ } _%> // https://vitejs.dev/config/ -export default ({ mode }) => { +export default ({ mode }: any) => { // import.meta.env.VITE_NAME available here with: process.env.VITE_NAME const env = loadEnv(mode, process.cwd()); process.env = {...process.env, ...env}; From 74bd8b6212fbeb9e6465fc85db7061aa46e24025 Mon Sep 17 00:00:00 2001 From: "yuzhe.sun" Date: Sun, 18 Feb 2024 18:27:32 +0800 Subject: [PATCH 5/6] exclude js file in public --- index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/index.ts b/index.ts index a74e5a375..224034156 100755 --- a/index.ts +++ b/index.ts @@ -505,6 +505,7 @@ async function init() { () => {}, (filepath) => { if (filepath.endsWith('.js')) { + if (filepath.indexOf('\\public\\') !== -1) return const tsFilePath = filepath.replace(/\.js$/, '.ts') if (fs.existsSync(tsFilePath)) { fs.unlinkSync(filepath) From 52f76feda26306a439f38eea233188729a4ae804 Mon Sep 17 00:00:00 2001 From: meatjam <851404658@qq.com> Date: Sun, 18 Feb 2024 22:14:31 +0800 Subject: [PATCH 6/6] update --- template/base/.eslintrc.cjs | 7 ++++--- template/base/package.json | 1 + template/base/src/api/apisTest.ts | 12 ++++++++++++ template/base/src/config/configIndex.ts | 19 +++++++++++++++++++ template/base/vite.config.js.ejs | 5 ++++- template/config/typescript/env.d.ts | 1 + 6 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 template/base/src/api/apisTest.ts create mode 100644 template/base/src/config/configIndex.ts diff --git a/template/base/.eslintrc.cjs b/template/base/.eslintrc.cjs index 0e3c48b7c..eafb89e9d 100644 --- a/template/base/.eslintrc.cjs +++ b/template/base/.eslintrc.cjs @@ -1,5 +1,5 @@ // @ts-check -require('@rushstack/eslint-patch/modern-module-resolution') +require('@rushstack/eslint-patch/modern-module-resolution'); /** * ESLint Configuration File * @@ -38,12 +38,13 @@ module.exports = { extends: ['eslint:recommended', 'plugin:prettier/recommended'], }, { - files: ['./public/**/*.js'], + files: ['./public/*.js'], env: { browser: true, }, parserOptions: { sourceType: 'module', + requireConfigFile: false, }, rules: { 'no-unused-vars': 'off', @@ -105,7 +106,7 @@ module.exports = { 'plugin:prettier/recommended', 'plugin:vue/vue3-essential', '@vue/eslint-config-typescript', - '@vue/eslint-config-prettier/skip-formatting' + '@vue/eslint-config-prettier/skip-formatting', ], rules: { 'no-unreachable': 'warn', diff --git a/template/base/package.json b/template/base/package.json index 7c86bcfca..431ab139f 100644 --- a/template/base/package.json +++ b/template/base/package.json @@ -14,6 +14,7 @@ "query-string": "^8.2.0" }, "devDependencies": { + "@babel/eslint-parser": "^7.23.10", "@vitejs/plugin-vue": "^5.0.3", "vite": "^5.0.11", "husky": "^9.0.11", diff --git a/template/base/src/api/apisTest.ts b/template/base/src/api/apisTest.ts new file mode 100644 index 000000000..53f99fd3d --- /dev/null +++ b/template/base/src/api/apisTest.ts @@ -0,0 +1,12 @@ +import { axios_backend_api } from '@/api/apiIndex'; + +/** + * 上报案件 + */ +export const apiUploadCase = (data: Record) => { + return axios_backend_api.request({ + url: '/api/si/scdld/upload', + method: 'post', + data, + }); +}; diff --git a/template/base/src/config/configIndex.ts b/template/base/src/config/configIndex.ts new file mode 100644 index 000000000..6985e1a11 --- /dev/null +++ b/template/base/src/config/configIndex.ts @@ -0,0 +1,19 @@ +import queryString from 'query-string'; + +const public_config = (window as Record)['CUSTOM_PUBLIC_CONFIG']; +const paramsObj = queryString.parse(window.location.search); + +const local_config = { + baseUrl: { + /*dev*/ + backend_dev: '//localhost:8088', + + /*pro*/ + backend_pro: BACKEND + '/api/test/', + }, + mockMode: !!1, +}; +const baseUrl_config = Object.assign({}, local_config.baseUrl, public_config.baseUrl); +const merge_config = Object.assign({}, local_config, public_config); +merge_config.baseUrl = baseUrl_config; +export default merge_config; diff --git a/template/base/vite.config.js.ejs b/template/base/vite.config.js.ejs index 670f18ee9..a6e44ab5e 100644 --- a/template/base/vite.config.js.ejs +++ b/template/base/vite.config.js.ejs @@ -20,6 +20,9 @@ export default ({ mode }: any) => { alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) } - } + }, + define: { + BACKEND: JSON.stringify(process.env.BACKEND), + }, }); } diff --git a/template/config/typescript/env.d.ts b/template/config/typescript/env.d.ts index 11f02fe2a..fea7405bf 100644 --- a/template/config/typescript/env.d.ts +++ b/template/config/typescript/env.d.ts @@ -1 +1,2 @@ /// +declare const BACKEND: string