create-vue3-enterprise 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,216 @@
1
+ #!/usr/bin/env node
2
+ import fs from 'node:fs';
3
+ import path from 'node:path';
4
+ import { fileURLToPath } from 'node:url';
5
+ import minimist from 'minimist';
6
+ import prompts from 'prompts';
7
+ import { red, green, cyan } from 'kolorist';
8
+ const argv = minimist(process.argv.slice(2), {
9
+ string: ['_'],
10
+ boolean: ['help', 'template', 'force'],
11
+ alias: {
12
+ h: 'help',
13
+ t: 'template',
14
+ f: 'force'
15
+ }
16
+ });
17
+ const cwd = process.cwd();
18
+ const __filename = fileURLToPath(import.meta.url);
19
+ const __dirname = path.dirname(__filename);
20
+ function printHelp() {
21
+ console.log(`
22
+ ${cyan('create-vue3-enterprise')}
23
+
24
+ ${green('Usage:')}
25
+ npm create vue3-enterprise <project-name> [options]
26
+
27
+ ${green('Options:')}
28
+ -h, --help Show help
29
+ -f, --force Force overwrite
30
+
31
+ ${green('Examples:')}
32
+ npm create vue3-enterprise my-project
33
+ `);
34
+ }
35
+ function isValidPackageName(projectName) {
36
+ return /^(?:@[a-z0-9-*~][a-z0-9-*._~]*\/)?[a-z0-9-~][a-z0-9-._~]*$/.test(projectName);
37
+ }
38
+ function toValidPackageName(projectName) {
39
+ return projectName.trim().toLowerCase().replace(/\s+/g, '-').replace(/^[._]/, '').replace(/[^a-z0-9-~]+/g, '-');
40
+ }
41
+ function emptyDir(dir) {
42
+ if (!fs.existsSync(dir))
43
+ return;
44
+ for (const file of fs.readdirSync(dir)) {
45
+ fs.rmSync(path.resolve(dir, file), { recursive: true, force: true });
46
+ }
47
+ }
48
+ function copyDir(srcDir, destDir) {
49
+ fs.mkdirSync(destDir, { recursive: true });
50
+ for (const file of fs.readdirSync(srcDir)) {
51
+ const srcFile = path.resolve(srcDir, file);
52
+ const destFile = path.resolve(destDir, file);
53
+ const stat = fs.statSync(srcFile);
54
+ if (stat.isDirectory())
55
+ copyDir(srcFile, destFile);
56
+ else
57
+ fs.copyFileSync(srcFile, destFile);
58
+ }
59
+ }
60
+ function makePkg(targetDir, features, needRouter, needPinia) {
61
+ const name = isValidPackageName(targetDir) ? targetDir : toValidPackageName(targetDir);
62
+ const pkg = {
63
+ name,
64
+ version: '0.0.0',
65
+ private: true,
66
+ type: 'module',
67
+ scripts: {
68
+ dev: 'vite',
69
+ build: 'vue-tsc && vite build',
70
+ preview: 'vite preview',
71
+ test: 'vitest',
72
+ 'test:e2e': 'playwright test',
73
+ 'test:perf': 'playwright test --config=playwright.config.perf.ts',
74
+ lint: 'eslint . --ext .vue,.ts,.tsx --fix',
75
+ format: 'prettier --write .',
76
+ 'type-check': 'vue-tsc --noEmit'
77
+ },
78
+ dependencies: { vue: '^3.4.0' },
79
+ devDependencies: {
80
+ '@vitejs/plugin-vue': '^5.0.0',
81
+ typescript: '^5.3.0',
82
+ vite: '^5.0.0',
83
+ 'vue-tsc': '^1.8.0'
84
+ }
85
+ };
86
+ if (needRouter)
87
+ pkg.dependencies['vue-router'] = '^4.2.0';
88
+ if (needPinia)
89
+ pkg.dependencies['pinia'] = '^2.1.0';
90
+ if (features.includes('lint')) {
91
+ Object.assign(pkg.devDependencies, {
92
+ '@typescript-eslint/eslint-plugin': '^6.21.0',
93
+ '@typescript-eslint/parser': '^6.21.0',
94
+ '@vue/eslint-config-prettier': '^9.0.0',
95
+ '@vue/eslint-config-typescript': '^12.0.0',
96
+ eslint: '^8.57.0',
97
+ 'eslint-plugin-vue': '^9.21.0',
98
+ prettier: '^3.2.0'
99
+ });
100
+ }
101
+ if (features.includes('vitest')) {
102
+ Object.assign(pkg.devDependencies, {
103
+ '@vue/test-utils': '^2.4.0',
104
+ 'happy-dom': '^13.0.0',
105
+ vitest: '^1.2.0'
106
+ });
107
+ }
108
+ if (features.includes('playwright')) {
109
+ pkg.devDependencies['@playwright/test'] = '^1.41.0';
110
+ }
111
+ if (features.includes('mcp')) {
112
+ pkg.devDependencies['vue3-enterprise-mcp'] = '^1.0.0';
113
+ }
114
+ if (features.includes('ci')) {
115
+ pkg.devDependencies['vue3-enterprise-ci'] = '^1.0.0';
116
+ }
117
+ return pkg;
118
+ }
119
+ async function main() {
120
+ console.log(`\n${cyan('Vue3 Enterprise Toolchain')}\n`);
121
+ if (argv.help) {
122
+ printHelp();
123
+ return;
124
+ }
125
+ let targetDir = argv._[0];
126
+ const response = await prompts([
127
+ {
128
+ type: targetDir ? null : 'text',
129
+ name: 'name',
130
+ message: 'Project name:',
131
+ initial: 'vue3-enterprise-project',
132
+ onState: (s) => { targetDir = String(s.value).trim() || 'vue3-enterprise-project'; }
133
+ },
134
+ {
135
+ type: 'select', name: 'template', message: 'Select template:',
136
+ choices: [
137
+ { title: 'Vue3 + TypeScript + Vite', value: 'vue3-ts' },
138
+ { title: 'Vue3 + TS + Vite + Pinia', value: 'vue3-ts-pinia' },
139
+ { title: 'Vue3 + TS + Vite + Pinia + Router', value: 'vue3-ts-full' }
140
+ ]
141
+ },
142
+ {
143
+ type: 'multiselect', name: 'features', message: 'Select features:',
144
+ choices: [
145
+ { title: 'ESLint + Prettier', value: 'lint', selected: true },
146
+ { title: 'Vitest', value: 'vitest', selected: true },
147
+ { title: 'Playwright', value: 'playwright', selected: true },
148
+ { title: 'Vue3 Enterprise MCP', value: 'mcp', selected: true },
149
+ { title: 'CI/CD Workflow', value: 'ci', selected: true },
150
+ { title: 'Performance Benchmark', value: 'perf', selected: true }
151
+ ]
152
+ },
153
+ {
154
+ type: 'confirm', name: 'router', message: 'Add Vue Router?', initial: true
155
+ },
156
+ {
157
+ type: 'confirm', name: 'pinia', message: 'Add Pinia?', initial: true
158
+ },
159
+ {
160
+ type: 'confirm', name: 'overwrite',
161
+ message: targetDir && fs.existsSync(targetDir) && fs.readdirSync(targetDir).length > 0
162
+ ? `Dir "${targetDir}" exists. Overwrite?` : 'Overwrite existing?',
163
+ initial: false
164
+ }
165
+ ], { onCancel: () => { console.log(red('✖ Cancelled')); process.exit(1); } });
166
+ if (!response.overwrite) {
167
+ console.log(red('✖ Cancelled'));
168
+ process.exit(1);
169
+ }
170
+ const root = path.join(cwd, targetDir);
171
+ if (fs.existsSync(root)) {
172
+ if (argv.force || response.overwrite)
173
+ emptyDir(root);
174
+ else {
175
+ console.log(red(`✖ Dir "${targetDir}" exists`));
176
+ process.exit(1);
177
+ }
178
+ }
179
+ else
180
+ fs.mkdirSync(root, { recursive: true });
181
+ console.log(`\n${cyan('Creating project...')}\n`);
182
+ copyDir(path.resolve(__dirname, '../template'), root);
183
+ const pkg = makePkg(targetDir, response.features || [], response.router, response.pinia);
184
+ fs.writeFileSync(path.join(root, 'package.json'), JSON.stringify(pkg, null, 2));
185
+ const desc = {
186
+ lint: '- 🧹 ESLint + Prettier',
187
+ vitest: '- 🧪 Vitest Unit Tests',
188
+ playwright: '- 🎭 Playwright E2E',
189
+ mcp: '- 🔍 Vue3 Enterprise MCP',
190
+ ci: '- ⚡ CI/CD',
191
+ perf: '- 📊 Performance'
192
+ };
193
+ const readme = `# ${pkg.name}
194
+
195
+ Created with Vue3 Enterprise Toolchain
196
+
197
+ ## Features
198
+ ${(response.features || []).map((f) => desc[f]).filter(Boolean).join('\n')}
199
+
200
+ ## Quick Start
201
+ \`\`\`bash
202
+ npm install
203
+ npm run dev
204
+ \`\`\`
205
+
206
+ ## Scripts
207
+ - \`npm run dev\` - Start dev server
208
+ - \`npm run build\` - Build
209
+ - \`npm test\` - Run tests
210
+ `;
211
+ fs.writeFileSync(path.join(root, 'README.md'), readme);
212
+ const gitignore = `node_modules\ndist\n*.local\n.vscode\ncoverage\ntest-results\nplaywright-report\n.perf-baseline.json`;
213
+ fs.writeFileSync(path.join(root, '.gitignore'), gitignore);
214
+ console.log(`${green('✔')} Created!\n cd ${cyan(targetDir)}\n npm install\n npm run dev\n`);
215
+ }
216
+ main().catch((e) => { console.error(e); process.exit(1); });
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "create-vue3-enterprise",
3
+ "version": "1.0.0",
4
+ "description": "Vue3 + TypeScript + Vite 企业级项目脚手架",
5
+ "type": "module",
6
+ "bin": {
7
+ "create-vue3-enterprise": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "template"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsc",
15
+ "dev": "tsc --watch",
16
+ "prepublishOnly": "npm run build",
17
+ "test": "node ./dist/index.js --help",
18
+ "test:create": "node ./dist/index.js test-project --force"
19
+ },
20
+ "dependencies": {
21
+ "kolorist": "^1.8.0",
22
+ "minimist": "^1.2.8",
23
+ "prompts": "^2.4.2"
24
+ },
25
+ "devDependencies": {
26
+ "@types/minimist": "^1.2.5",
27
+ "@types/node": "^20.0.0",
28
+ "@types/prompts": "^2.4.9",
29
+ "typescript": "^5.3.0"
30
+ }
31
+ }
@@ -0,0 +1,13 @@
1
+ # EditorConfig
2
+ root = true
3
+
4
+ [*]
5
+ charset = utf-8
6
+ indent_style = space
7
+ indent_size = 2
8
+ end_of_line = lf
9
+ insert_final_newline = true
10
+ trim_trailing_whitespace = true
11
+
12
+ [*.md]
13
+ trim_trailing_whitespace = false
@@ -0,0 +1,21 @@
1
+ /* eslint-env node */
2
+ require('@rushstack/eslint-patch/modern-module-resolution')
3
+
4
+ module.exports = {
5
+ root: true,
6
+ 'extends': [
7
+ 'plugin:vue/vue3-essential',
8
+ 'eslint:recommended',
9
+ '@vue/eslint-config-typescript',
10
+ '@vue/eslint-config-prettier/skip-formatting'
11
+ ],
12
+ parserOptions: {
13
+ ecmaVersion: 'latest'
14
+ },
15
+ rules: {
16
+ 'vue/multi-word-component-names': 'off',
17
+ '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
18
+ 'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
19
+ 'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off'
20
+ }
21
+ }
@@ -0,0 +1,70 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main, master]
6
+ pull_request:
7
+ branches: [main, master]
8
+
9
+ jobs:
10
+ lint:
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - uses: actions/checkout@v4
14
+ - uses: actions/setup-node@v4
15
+ with:
16
+ node-version: '20'
17
+ cache: 'npm'
18
+ - run: npm ci
19
+ - run: npm run lint
20
+ - run: npm run type-check
21
+
22
+ test:
23
+ runs-on: ubuntu-latest
24
+ steps:
25
+ - uses: actions/checkout@v4
26
+ - uses: actions/setup-node@v4
27
+ with:
28
+ node-version: '20'
29
+ cache: 'npm'
30
+ - run: npm ci
31
+ - run: npm test -- --run
32
+
33
+ e2e:
34
+ runs-on: ubuntu-latest
35
+ steps:
36
+ - uses: actions/checkout@v4
37
+ - uses: actions/setup-node@v4
38
+ with:
39
+ node-version: '20'
40
+ cache: 'npm'
41
+ - run: npm ci
42
+ - run: npx playwright install --with-deps
43
+ - run: npm run test:e2e
44
+ - uses: actions/upload-artifact@v4
45
+ if: always()
46
+ with:
47
+ name: playwright-report
48
+ path: playwright-report/
49
+ retention-days: 30
50
+
51
+ performance:
52
+ runs-on: ubuntu-latest
53
+ needs: [lint, test]
54
+ steps:
55
+ - uses: actions/checkout@v4
56
+ - uses: actions/setup-node@v4
57
+ with:
58
+ node-version: '20'
59
+ cache: 'npm'
60
+ - run: npm ci
61
+ - name: Run Performance Tests
62
+ run: npx vue3-enterprise-ci run-perf
63
+ env:
64
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
65
+ - name: Upload Performance Report
66
+ uses: actions/upload-artifact@v4
67
+ with:
68
+ name: performance-report
69
+ path: perf-report/
70
+ retention-days: 30
@@ -0,0 +1,8 @@
1
+ {
2
+ "semi": false,
3
+ "singleQuote": true,
4
+ "trailingComma": "es5",
5
+ "tabWidth": 2,
6
+ "printWidth": 100,
7
+ "endOfLine": "lf"
8
+ }
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
+ <title>Vue3 Enterprise</title>
8
+ </head>
9
+ <body>
10
+ <div id="app"></div>
11
+ <script type="module" src="/src/main.ts"></script>
12
+ </body>
13
+ </html>
@@ -0,0 +1,33 @@
1
+ import { defineConfig, devices } from '@playwright/test'
2
+
3
+ export default defineConfig({
4
+ testDir: './tests/e2e',
5
+ fullyParallel: true,
6
+ forbidOnly: !!process.env.CI,
7
+ retries: process.env.CI ? 2 : 0,
8
+ workers: process.env.CI ? 1 : undefined,
9
+ reporter: 'html',
10
+ use: {
11
+ baseURL: 'http://localhost:5173',
12
+ trace: 'on-first-retry',
13
+ },
14
+ projects: [
15
+ {
16
+ name: 'chromium',
17
+ use: { ...devices['Desktop Chrome'] },
18
+ },
19
+ {
20
+ name: 'firefox',
21
+ use: { ...devices['Desktop Firefox'] },
22
+ },
23
+ {
24
+ name: 'webkit',
25
+ use: { ...devices['Desktop Safari'] },
26
+ },
27
+ ],
28
+ webServer: {
29
+ command: 'npm run dev',
30
+ url: 'http://localhost:5173',
31
+ reuseExistingServer: !process.env.CI,
32
+ },
33
+ })
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.906-4.828c2.372-.72 4.746 1.449 4.151 3.828l-12.127 58.781c-.856 4.156 4.64 6.425 6.936 3.038l.066-.085L186.05 74.64c1.301-1.828-.225-4.303-2.356-3.87l-25.563 5.13c-2.418.484-4.487-1.77-3.808-4.154l16.862-60.374c.68-2.44-1.474-4.667-3.941-4.155L185.432.063Z"></path></svg>
@@ -0,0 +1,34 @@
1
+ <script setup lang="ts">
2
+ import { ref } from 'vue'
3
+ import HelloWorld from './components/HelloWorld.vue'
4
+
5
+ const count = ref(0)
6
+ </script>
7
+
8
+ <template>
9
+ <div>
10
+ <a href="https://vitejs.dev" target="_blank">
11
+ <img src="/vite.svg" class="logo" alt="Vite logo" />
12
+ </a>
13
+ <a href="https://vuejs.org/" target="_blank">
14
+ <img src="./assets/vue.svg" class="logo vue" alt="Vue logo" />
15
+ </a>
16
+ </div>
17
+ <HelloWorld msg="Vue3 Enterprise" />
18
+ <button type="button" @click="count++">count is {{ count }}</button>
19
+ </template>
20
+
21
+ <style scoped>
22
+ .logo {
23
+ height: 6em;
24
+ padding: 1.5em;
25
+ will-change: filter;
26
+ transition: filter 300ms;
27
+ }
28
+ .logo:hover {
29
+ filter: drop-shadow(0 0 2em #646cffaa);
30
+ }
31
+ .logo.vue:hover {
32
+ filter: drop-shadow(0 0 2em #42b883aa);
33
+ }
34
+ </style>
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>
@@ -0,0 +1,35 @@
1
+ <script setup lang="ts">
2
+ defineProps<{
3
+ msg: string
4
+ }>()
5
+ </script>
6
+
7
+ <template>
8
+ <h1>{{ msg }}</h1>
9
+
10
+ <p>
11
+ Recommended IDE setup:
12
+ <a href="https://code.visualstudio.com/" target="_blank">VSCode</a>
13
+ +
14
+ <a href="https://github.com/johnsoncodehk/volar" target="_blank">Volar</a>
15
+ </p>
16
+
17
+ <p>
18
+ <a href="https://vitejs.dev/guide/features.html" target="_blank">
19
+ Vite Documentation
20
+ </a>
21
+ |
22
+ <a href="https://v3.vuejs.org/" target="_blank">Vue 3 Documentation</a>
23
+ </p>
24
+
25
+ <p>
26
+ Edit
27
+ <code>components/HelloWorld.vue</code> to test hot module replacement.
28
+ </p>
29
+ </template>
30
+
31
+ <style scoped>
32
+ a {
33
+ color: #42b883;
34
+ }
35
+ </style>
@@ -0,0 +1,5 @@
1
+ import { createApp } from 'vue'
2
+ import './style.css'
3
+ import App from './App.vue'
4
+
5
+ createApp(App).mount('#app')
@@ -0,0 +1,80 @@
1
+ :root {
2
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
3
+ line-height: 1.5;
4
+ font-weight: 400;
5
+
6
+ color-scheme: light dark;
7
+ color: rgba(255, 255, 255, 0.87);
8
+ background-color: #242424;
9
+
10
+ font-synthesis: none;
11
+ text-rendering: optimizeLegibility;
12
+ -webkit-font-smoothing: antialiased;
13
+ -moz-osx-font-smoothing: grayscale;
14
+ -webkit-text-size-adjust: 100%;
15
+ }
16
+
17
+ a {
18
+ font-weight: 500;
19
+ color: #646cff;
20
+ text-decoration: inherit;
21
+ }
22
+ a:hover {
23
+ color: #535bf2;
24
+ }
25
+
26
+ body {
27
+ margin: 0;
28
+ display: flex;
29
+ place-items: center;
30
+ min-width: 320px;
31
+ min-height: 100vh;
32
+ }
33
+
34
+ h1 {
35
+ font-size: 3.2em;
36
+ line-height: 1.1;
37
+ }
38
+
39
+ button {
40
+ border-radius: 8px;
41
+ border: 1px solid transparent;
42
+ padding: 0.6em 1.2em;
43
+ font-size: 1em;
44
+ font-weight: 500;
45
+ font-family: inherit;
46
+ background-color: #1a1a1a;
47
+ cursor: pointer;
48
+ transition: border-color 0.25s;
49
+ }
50
+ button:hover {
51
+ border-color: #646cff;
52
+ }
53
+ button:focus,
54
+ button:focus-visible {
55
+ outline: 4px auto -webkit-focus-ring-color;
56
+ }
57
+
58
+ .card {
59
+ padding: 2em;
60
+ }
61
+
62
+ #app {
63
+ max-width: 1280px;
64
+ margin: 0 auto;
65
+ padding: 2rem;
66
+ text-align: center;
67
+ }
68
+
69
+ @media (prefers-color-scheme: light) {
70
+ :root {
71
+ color: #213547;
72
+ background-color: #ffffff;
73
+ }
74
+ a:hover {
75
+ color: #747bff;
76
+ }
77
+ button {
78
+ background-color: #f9f9f9;
79
+ }
80
+ }
@@ -0,0 +1,23 @@
1
+ import { test, expect } from '@playwright/test'
2
+
3
+ test('homepage has title and links', async ({ page }) => {
4
+ await page.goto('/')
5
+
6
+ await expect(page).toHaveTitle(/Vue3/)
7
+
8
+ const viteLink = page.locator('a[href="https://vitejs.dev"]')
9
+ await expect(viteLink).toBeVisible()
10
+
11
+ const vueLink = page.locator('a[href="https://vuejs.org/"]')
12
+ await expect(vueLink).toBeVisible()
13
+ })
14
+
15
+ test('counter increments on click', async ({ page }) => {
16
+ await page.goto('/')
17
+
18
+ const button = page.locator('button')
19
+ await expect(button).toHaveText('count is 0')
20
+
21
+ await button.click()
22
+ await expect(button).toHaveText('count is 1')
23
+ })
@@ -0,0 +1,10 @@
1
+ import { describe, it, expect } from 'vitest'
2
+ import { mount } from '@vue/test-utils'
3
+ import HelloWorld from '../../src/components/HelloWorld.vue'
4
+
5
+ describe('HelloWorld', () => {
6
+ it('renders properly', () => {
7
+ const wrapper = mount(HelloWorld, { props: { msg: 'Hello Vitest' } })
8
+ expect(wrapper.text()).toContain('Hello Vitest')
9
+ })
10
+ })
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "module": "ESNext",
6
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
7
+ "skipLibCheck": true,
8
+ "moduleResolution": "bundler",
9
+ "allowImportingTsExtensions": true,
10
+ "resolveJsonModule": true,
11
+ "isolatedModules": true,
12
+ "noEmit": true,
13
+ "jsx": "preserve",
14
+ "strict": true,
15
+ "noUnusedLocals": true,
16
+ "noUnusedParameters": true,
17
+ "noFallthroughCasesInSwitch": true
18
+ },
19
+ "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
20
+ "references": [{ "path": "./tsconfig.node.json" }]
21
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "compilerOptions": {
3
+ "composite": true,
4
+ "skipLibCheck": true,
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "allowSyntheticDefaultImports": true
8
+ },
9
+ "include": ["vite.config.ts"]
10
+ }
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from 'vite'
2
+ import vue from '@vitejs/plugin-vue'
3
+
4
+ export default defineConfig({
5
+ plugins: [vue()],
6
+ test: {
7
+ environment: 'happy-dom'
8
+ }
9
+ })
@@ -0,0 +1,17 @@
1
+ import { defineConfig } from 'vitest/config'
2
+ import vue from '@vitejs/plugin-vue'
3
+
4
+ export default defineConfig({
5
+ plugins: [vue()],
6
+ test: {
7
+ globals: true,
8
+ environment: 'happy-dom',
9
+ include: ['tests/unit/**/*.spec.ts'],
10
+ coverage: {
11
+ provider: 'v8',
12
+ reporter: ['text', 'json', 'html'],
13
+ include: ['src/**/*'],
14
+ exclude: ['src/**/*.d.ts', 'src/main.ts']
15
+ }
16
+ }
17
+ })