From 5843068d3b15607aaf50bdc319022ea6ebd1907a Mon Sep 17 00:00:00 2001 From: Colum Ferry Date: Thu, 27 Jun 2024 15:48:37 +0100 Subject: [PATCH] fix(vue): application generator should use normalized app name #26605 (#26729) ## Current Behavior The `vue` app generator is not using the normalized name produced by `projectRootAndFormat` util when creating the application. This leads to errors in some cases. ## Expected Behavior Use the `projectName` produced by the value to create the project correctly. ## Related Issue(s) Fixes #26605 --- .../__snapshots__/application.spec.ts.snap | 163 ++++++++++++++++++ .../application/application.spec.ts | 14 ++ .../src/generators/application/application.ts | 2 +- .../generators/application/lib/add-vite.ts | 8 +- .../application/lib/normalize-options.ts | 9 - 5 files changed, 182 insertions(+), 14 deletions(-) diff --git a/packages/vue/src/generators/application/__snapshots__/application.spec.ts.snap b/packages/vue/src/generators/application/__snapshots__/application.spec.ts.snap index 6c84238a269db..d484c2252148b 100644 --- a/packages/vue/src/generators/application/__snapshots__/application.spec.ts.snap +++ b/packages/vue/src/generators/application/__snapshots__/application.spec.ts.snap @@ -1,5 +1,168 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`application generator should set up project correctly with PascalCase name 1`] = ` +"{ + "root": true, + "ignorePatterns": ["**/*"], + "plugins": ["@nx"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx", "*.vue"], + "rules": { + "@nx/enforce-module-boundaries": [ + "error", + { + "enforceBuildableLibDependency": true, + "allow": [], + "depConstraints": [ + { + "sourceTag": "*", + "onlyDependOnLibsWithTags": ["*"] + } + ] + } + ] + } + }, + { + "files": ["*.ts", "*.tsx"], + "extends": ["plugin:@nx/typescript"], + "rules": {} + }, + { + "files": ["*.js", "*.jsx"], + "extends": ["plugin:@nx/javascript"], + "rules": {} + } + ] +} +" +`; + +exports[`application generator should set up project correctly with PascalCase name 2`] = ` +"/// +import { defineConfig } from 'vite'; +import vue from '@vitejs/plugin-vue'; +import { nxViteTsPaths } from '@nx/vite/plugins/nx-tsconfig-paths.plugin'; + +export default defineConfig({ + root: __dirname, + cacheDir: '../node_modules/.vite/TestApp', + + server: { + port: 4200, + host: 'localhost', + }, + + preview: { + port: 4300, + host: 'localhost', + }, + + plugins: [vue(), nxViteTsPaths()], + + // Uncomment this if you are using workers. + // worker: { + // plugins: [ nxViteTsPaths() ], + // }, + + build: { + outDir: '../dist/TestApp', + emptyOutDir: true, + reportCompressedSize: true, + commonjsOptions: { + transformMixedEsModules: true, + }, + }, + + test: { + watch: false, + globals: true, + cache: { + dir: '../node_modules/.vitest/TestApp', + }, + environment: 'jsdom', + include: ['src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'], + + reporters: ['default'], + coverage: { + reportsDirectory: '../coverage/TestApp', + provider: 'v8', + }, + }, +}); +" +`; + +exports[`application generator should set up project correctly with PascalCase name 3`] = ` +"{ + "extends": [ + "plugin:vue/vue3-essential", + "eslint:recommended", + "@vue/eslint-config-typescript", + "@vue/eslint-config-prettier/skip-formatting", + "../.eslintrc.json" + ], + "ignorePatterns": ["!**/*"], + "overrides": [ + { + "files": ["*.ts", "*.tsx", "*.js", "*.jsx", "*.vue"], + "rules": { + "vue/multi-word-component-names": "off" + } + } + ] +} +" +`; + +exports[`application generator should set up project correctly with PascalCase name 4`] = ` +"import { describe, it, expect } from 'vitest'; + +import { mount } from '@vue/test-utils'; +import App from './App.vue'; + +describe('App', () => { + it('renders properly', async () => { + const wrapper = mount(App, {}); + + expect(wrapper.text()).toContain('Welcome TestApp 👋'); + }); +}); +" +`; + +exports[`application generator should set up project correctly with PascalCase name 5`] = ` +[ + ".eslintignore", + ".eslintrc.json", + ".prettierignore", + ".prettierrc", + ".vscode/extensions.json", + "nx.json", + "package.json", + "TestApp-e2e/.eslintrc.json", + "TestApp-e2e/playwright.config.ts", + "TestApp-e2e/project.json", + "TestApp-e2e/src/example.spec.ts", + "TestApp-e2e/tsconfig.json", + "TestApp/.eslintrc.json", + "TestApp/index.html", + "TestApp/project.json", + "TestApp/src/app/App.spec.ts", + "TestApp/src/app/App.vue", + "TestApp/src/app/NxWelcome.vue", + "TestApp/src/main.ts", + "TestApp/src/styles.css", + "TestApp/tsconfig.app.json", + "TestApp/tsconfig.json", + "TestApp/tsconfig.spec.json", + "TestApp/vite.config.ts", + "tsconfig.base.json", + "vitest.workspace.ts", +] +`; + exports[`application generator should set up project correctly with given options 1`] = ` "{ "root": true, diff --git a/packages/vue/src/generators/application/application.spec.ts b/packages/vue/src/generators/application/application.spec.ts index 02650c5285ebf..3fbbccfaaaab1 100644 --- a/packages/vue/src/generators/application/application.spec.ts +++ b/packages/vue/src/generators/application/application.spec.ts @@ -29,6 +29,20 @@ describe('application generator', () => { expect(listFiles(tree)).toMatchSnapshot(); }); + it('should set up project correctly with PascalCase name', async () => { + await applicationGenerator(tree, { + ...options, + name: 'TestApp', + unitTestRunner: 'vitest', + projectNameAndRootFormat: 'as-provided', + }); + expect(tree.read('.eslintrc.json', 'utf-8')).toMatchSnapshot(); + expect(tree.read('TestApp/vite.config.ts', 'utf-8')).toMatchSnapshot(); + expect(tree.read('TestApp/.eslintrc.json', 'utf-8')).toMatchSnapshot(); + expect(tree.read('TestApp/src/app/App.spec.ts', 'utf-8')).toMatchSnapshot(); + expect(listFiles(tree)).toMatchSnapshot(); + }); + it('should not use stylesheet if --style=none', async () => { await applicationGenerator(tree, { ...options, style: 'none' }); diff --git a/packages/vue/src/generators/application/application.ts b/packages/vue/src/generators/application/application.ts index f6efb1b7f944e..d19a59c0b16b9 100644 --- a/packages/vue/src/generators/application/application.ts +++ b/packages/vue/src/generators/application/application.ts @@ -32,7 +32,7 @@ export async function applicationGeneratorInternal( const tasks: GeneratorCallback[] = []; - addProjectConfiguration(tree, options.name, { + addProjectConfiguration(tree, options.projectName, { root: options.appProjectRoot, projectType: 'application', sourceRoot: `${options.appProjectRoot}/src`, diff --git a/packages/vue/src/generators/application/lib/add-vite.ts b/packages/vue/src/generators/application/lib/add-vite.ts index 0e7df5a39737d..efc185452876b 100644 --- a/packages/vue/src/generators/application/lib/add-vite.ts +++ b/packages/vue/src/generators/application/lib/add-vite.ts @@ -15,7 +15,7 @@ export async function addVite( // Set up build target (and test target if using vitest) const viteTask = await viteConfigurationGenerator(tree, { uiFramework: 'none', - project: options.name, + project: options.projectName, newProject: true, inSourceTests: options.inSourceTests, includeVitest: options.unitTestRunner === 'vitest', @@ -27,7 +27,7 @@ export async function addVite( createOrEditViteConfig( tree, { - project: options.name, + project: options.projectName, includeLib: false, includeVitest: options.unitTestRunner === 'vitest', inSourceTests: options.inSourceTests, @@ -39,10 +39,10 @@ export async function addVite( // Update build to skip type checking since tsc won't work on .vue files. // Need to use vue-tsc instead. - const projectConfig = readProjectConfiguration(tree, options.name); + const projectConfig = readProjectConfiguration(tree, options.projectName); if (projectConfig.targets?.build?.options) { projectConfig.targets.build.options.skipTypeCheck = true; - updateProjectConfiguration(tree, options.name, projectConfig); + updateProjectConfiguration(tree, options.projectName, projectConfig); } return viteTask; diff --git a/packages/vue/src/generators/application/lib/normalize-options.ts b/packages/vue/src/generators/application/lib/normalize-options.ts index 8105c051d323c..f8c5d154af7e1 100644 --- a/packages/vue/src/generators/application/lib/normalize-options.ts +++ b/packages/vue/src/generators/application/lib/normalize-options.ts @@ -2,14 +2,6 @@ import { Tree, extractLayoutDirectory, names } from '@nx/devkit'; import { determineProjectNameAndRootOptions } from '@nx/devkit/src/generators/project-name-and-root-utils'; import { NormalizedSchema, Schema } from '../schema'; -export function normalizeDirectory(options: Schema) { - options.directory = options.directory?.replace(/\\{1,2}/g, '/'); - const { projectDirectory } = extractLayoutDirectory(options.directory); - return projectDirectory - ? `${names(projectDirectory).fileName}/${names(options.name).fileName}` - : names(options.name).fileName; -} - export async function normalizeOptions( host: Tree, options: Schema, @@ -39,7 +31,6 @@ export async function normalizeOptions( const normalized = { ...options, - name: names(options.name).fileName, projectName: appProjectName, appProjectRoot, e2eProjectName,