fix(vue): application generator should use normalized app name #26605 (#26729)

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->
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
<!-- This is the behavior we should expect with the changes in this PR
-->
Use the `projectName` produced by the value to create the project
correctly.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #26605
This commit is contained in:
Colum Ferry 2024-06-27 15:48:37 +01:00 committed by GitHub
parent 544eff02b4
commit 5843068d3b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 182 additions and 14 deletions

View File

@ -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`] = `
"/// <reference types='vitest' />
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,

View File

@ -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' });

View File

@ -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`,

View File

@ -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;

View File

@ -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,