diff --git a/packages/devkit/src/generators/artifact-name-and-directory-utils.ts b/packages/devkit/src/generators/artifact-name-and-directory-utils.ts index fcf2872ee4248..ac71f7d5c5f35 100644 --- a/packages/devkit/src/generators/artifact-name-and-directory-utils.ts +++ b/packages/devkit/src/generators/artifact-name-and-directory-utils.ts @@ -23,7 +23,7 @@ export type ArtifactGenerationOptions = { name: string; directory?: string; disallowPathInNameForDerived?: boolean; - fileExtension?: 'js' | 'jsx' | 'ts' | 'tsx'; + fileExtension?: 'js' | 'jsx' | 'ts' | 'tsx' | 'vue'; fileName?: string; flat?: boolean; nameAndDirectoryFormat?: NameAndDirectoryFormat; diff --git a/packages/nuxt/src/generators/component/component.ts b/packages/nuxt/src/generators/component/component.ts index e5710103d4240..cbfe22c37433b 100644 --- a/packages/nuxt/src/generators/component/component.ts +++ b/packages/nuxt/src/generators/component/component.ts @@ -1,4 +1,4 @@ -import { formatFiles, runTasksInSerial, Tree } from '@nx/devkit'; +import { formatFiles, Tree } from '@nx/devkit'; import { componentGenerator as vueComponentGenerator } from '@nx/vue'; import { Schema } from './schema'; @@ -7,17 +7,16 @@ import { Schema } from './schema'; * are just adjusting some options */ export async function componentGenerator(host: Tree, options: Schema) { - const componentGenerator = await vueComponentGenerator(host, { + await vueComponentGenerator(host, { ...options, routing: false, skipFormat: true, + directory: options.directory ?? 'components', }); if (!options.skipFormat) { await formatFiles(host); } - - return runTasksInSerial(componentGenerator); } export default componentGenerator; diff --git a/packages/nuxt/src/generators/page/page.spec.ts b/packages/nuxt/src/generators/page/page.spec.ts index bde9733e59a50..7f36e64acce03 100644 --- a/packages/nuxt/src/generators/page/page.spec.ts +++ b/packages/nuxt/src/generators/page/page.spec.ts @@ -16,12 +16,8 @@ describe('page', () => { expect(getDirectory('pages/someDir')).toEqual('pages/someDir'); }); - it('should append "/pages" to the directory if it does not start with "pages/" 2', () => { - expect(getDirectory('someDir/')).toEqual('someDir/pages'); - }); - - it('should append "/pages" to the directory if it does not start with "pages/"', () => { - expect(getDirectory('someDir')).toEqual('someDir/pages'); + it('should prepend "pages/" to the directory if it does not start with "pages/"', () => { + expect(getDirectory('someDir')).toEqual('pages/someDir'); }); it('should work with an empty string', () => { diff --git a/packages/nuxt/src/generators/page/page.ts b/packages/nuxt/src/generators/page/page.ts index aa16daab5b1d4..d005920f002a7 100644 --- a/packages/nuxt/src/generators/page/page.ts +++ b/packages/nuxt/src/generators/page/page.ts @@ -1,14 +1,9 @@ -import { - formatFiles, - joinPathFragments, - runTasksInSerial, - Tree, -} from '@nx/devkit'; +import { formatFiles, joinPathFragments, Tree } from '@nx/devkit'; import { componentGenerator } from '../component/component'; import { Schema } from './schema'; export async function pageGenerator(host: Tree, options: Schema) { - const pageGenerator = await componentGenerator(host, { + await componentGenerator(host, { ...options, directory: getDirectory(options.directory), skipTests: true, @@ -21,15 +16,13 @@ export async function pageGenerator(host: Tree, options: Schema) { if (!options.skipFormat) { await formatFiles(host); } - - return runTasksInSerial(pageGenerator); } export function getDirectory(directory: string) { return directory?.length > 0 ? directory.startsWith('pages/') ? directory - : joinPathFragments(directory + '/pages') + : joinPathFragments('pages', directory) : 'pages'; } diff --git a/packages/vue/generators.json b/packages/vue/generators.json index b601513ac5036..77c2beff5d8dd 100644 --- a/packages/vue/generators.json +++ b/packages/vue/generators.json @@ -23,7 +23,7 @@ "description": "Create a Vue library." }, "component": { - "factory": "./src/generators/component/component", + "factory": "./src/generators/component/component#componentGeneratorInternal", "schema": "./src/generators/component/schema.json", "aliases": ["c"], "x-type": "component", diff --git a/packages/vue/src/generators/component/__snapshots__/component.spec.ts.snap b/packages/vue/src/generators/component/__snapshots__/component.spec.ts.snap deleted file mode 100644 index a25bc2f454d5f..0000000000000 --- a/packages/vue/src/generators/component/__snapshots__/component.spec.ts.snap +++ /dev/null @@ -1,62 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`component --export should add to index.ts barrel 1`] = ` -"export { default as Hello } from './components/hello/hello.vue'; -" -`; - -exports[`component --export should not export from an app 1`] = `null`; - -exports[`component should generate files with jest 1`] = ` -" - - - - -" -`; - -exports[`component should generate files with jest 2`] = ` -"import { mount } from '@vue/test-utils'; -import Hello from './hello.vue'; - -describe('Hello', () => { - it('renders properly', () => { - const wrapper = mount(Hello, {}); - expect(wrapper.text()).toContain('Welcome to Hello'); - }); -}); -" -`; - -exports[`component should generate files with vitest 1`] = ` -" - - - - -" -`; - -exports[`component should generate files with vitest 2`] = ` -"import { describe, it, expect } from 'vitest'; - -import { mount } from '@vue/test-utils'; -import Hello from './hello.vue'; - -describe('Hello', () => { - it('renders properly', () => { - const wrapper = mount(Hello, {}); - expect(wrapper.text()).toContain('Welcome to Hello'); - }); -}); -" -`; diff --git a/packages/vue/src/generators/component/component.spec.ts b/packages/vue/src/generators/component/component.spec.ts index 546f29173d932..683cefb871518 100644 --- a/packages/vue/src/generators/component/component.spec.ts +++ b/packages/vue/src/generators/component/component.spec.ts @@ -29,12 +29,34 @@ describe('component', () => { unitTestRunner: 'vitest', }); - expect( - appTree.read(`${libName}/src/components/hello/hello.vue`, 'utf-8') - ).toMatchSnapshot(); - expect( - appTree.read(`${libName}/src/components/hello/hello.spec.ts`, 'utf-8') - ).toMatchSnapshot(); + expect(appTree.read(`${libName}/src/lib/hello/hello.vue`, 'utf-8')) + .toMatchInlineSnapshot(` + " + + + + + " + `); + expect(appTree.read(`${libName}/src/lib/hello/hello.spec.ts`, 'utf-8')) + .toMatchInlineSnapshot(` + "import { describe, it, expect } from 'vitest'; + + import { mount } from '@vue/test-utils'; + import Hello from './hello.vue'; + + describe('Hello', () => { + it('renders properly', () => { + const wrapper = mount(Hello, {}); + expect(wrapper.text()).toContain('Welcome to Hello'); + }); + }); + " + `); }); it('should generate files with jest', async () => { @@ -44,12 +66,32 @@ describe('component', () => { unitTestRunner: 'jest', }); - expect( - appTree.read(`${libName}/src/components/hello/hello.vue`, 'utf-8') - ).toMatchSnapshot(); - expect( - appTree.read(`${libName}/src/components/hello/hello.spec.ts`, 'utf-8') - ).toMatchSnapshot(); + expect(appTree.read(`${libName}/src/lib/hello/hello.vue`, 'utf-8')) + .toMatchInlineSnapshot(` + " + + + + + " + `); + expect(appTree.read(`${libName}/src/lib/hello/hello.spec.ts`, 'utf-8')) + .toMatchInlineSnapshot(` + "import { mount } from '@vue/test-utils'; + import Hello from './hello.vue'; + + describe('Hello', () => { + it('renders properly', () => { + const wrapper = mount(Hello, {}); + expect(wrapper.text()).toContain('Welcome to Hello'); + }); + }); + " + `); }); it('should have correct component name based on directory', async () => { @@ -61,7 +103,10 @@ describe('component', () => { }); expect( - appTree.read(`${libName}/src/foo/bar/hello-world.vue`, 'utf-8') + appTree.read( + `${libName}/src/foo/bar/hello-world/hello-world.vue`, + 'utf-8' + ) ).toContain('HelloWorld'); }); @@ -74,7 +119,10 @@ describe('component', () => { }); expect( - appTree.read(`${libName}/src/foo/bar-baz/hello-world.vue`, 'utf-8') + appTree.read( + `${libName}/src/foo/bar-baz/hello-world/hello-world.vue`, + 'utf-8' + ) ).toContain('HelloWorld'); }); @@ -86,10 +134,10 @@ describe('component', () => { }); expect( - appTree.read(`${appName}/src/components/hello/hello.vue`, 'utf-8') + appTree.read(`${appName}/src/app/hello/hello.vue`, 'utf-8') ).toContain('Hello'); expect( - appTree.exists(`${appName}/src/components/hello/hello.spec.ts`) + appTree.exists(`${appName}/src/app/hello/hello.spec.ts`) ).toBeTruthy(); }); @@ -100,9 +148,11 @@ describe('component', () => { project: libName, export: true, }); - expect( - appTree.read(`${libName}/src/index.ts`, 'utf-8') - ).toMatchSnapshot(); + expect(appTree.read(`${libName}/src/index.ts`, 'utf-8')) + .toMatchInlineSnapshot(` + "export { default as Hello } from './lib/hello/hello.vue'; + " + `); }); it('should not export from an app', async () => { @@ -112,9 +162,7 @@ describe('component', () => { export: true, }); - expect( - appTree.read(`${appName}/src/index.ts`, 'utf-8') - ).toMatchSnapshot(); + expect(appTree.exists(`${appName}/src/index.ts`)).toBe(false); }); }); @@ -127,10 +175,10 @@ describe('component', () => { directory: 'foo/bar', }); expect( - appTree.read(`${libName}/src/foo/bar/Hello.vue`, 'utf-8') + appTree.read(`${libName}/src/foo/bar/hello/Hello.vue`, 'utf-8') ).toContain('Hello'); expect( - appTree.exists(`${libName}/src/foo/bar/Hello.spec.ts`) + appTree.exists(`${libName}/src/foo/bar/hello/Hello.spec.ts`) ).toBeTruthy(); }); }); @@ -144,12 +192,10 @@ describe('component', () => { pascalCaseDirectory: true, }); expect( - appTree.exists(`${libName}/src/components/HelloWorld/HelloWorld.vue`) + appTree.exists(`${libName}/src/lib/HelloWorld/HelloWorld.vue`) ).toBeTruthy(); expect( - appTree.exists( - `${libName}/src/components/HelloWorld/HelloWorld.spec.ts` - ) + appTree.exists(`${libName}/src/lib/HelloWorld/HelloWorld.spec.ts`) ).toBeTruthy(); }); }); @@ -162,7 +208,7 @@ describe('component', () => { flat: true, }); - expect(appTree.exists(`${libName}/src/components/hello.vue`)); + expect(appTree.exists(`${libName}/src/lib/hello.vue`)); }); it('should work with custom directory path', async () => { await componentGenerator(appTree, { diff --git a/packages/vue/src/generators/component/component.ts b/packages/vue/src/generators/component/component.ts index c2ba8210f27fa..5f5cc37aac83a 100644 --- a/packages/vue/src/generators/component/component.ts +++ b/packages/vue/src/generators/component/component.ts @@ -1,39 +1,28 @@ -import { - formatFiles, - generateFiles, - GeneratorCallback, - joinPathFragments, - runTasksInSerial, - toJS, - Tree, -} from '@nx/devkit'; -import { NormalizedSchema, Schema } from './schema'; +import { formatFiles, generateFiles, toJS, Tree } from '@nx/devkit'; import { join } from 'path'; import { addExportsToBarrel, normalizeOptions } from './lib/utils'; +import { NormalizedSchema, Schema } from './schema'; export async function componentGenerator(host: Tree, schema: Schema) { + return componentGeneratorInternal(host, { + nameAndDirectoryFormat: 'derived', + ...schema, + }); +} + +export async function componentGeneratorInternal(host: Tree, schema: Schema) { const options = await normalizeOptions(host, schema); createComponentFiles(host, options); - - const tasks: GeneratorCallback[] = []; - addExportsToBarrel(host, options); if (!options.skipFormat) { await formatFiles(host); } - - return runTasksInSerial(...tasks); } function createComponentFiles(host: Tree, options: NormalizedSchema) { - const componentDir = joinPathFragments( - options.projectSourceRoot, - options.directory - ); - - generateFiles(host, join(__dirname, './files'), componentDir, { + generateFiles(host, join(__dirname, './files'), options.directory, { ...options, tmpl: '', unitTestRunner: options.unitTestRunner, diff --git a/packages/vue/src/generators/component/lib/utils.ts b/packages/vue/src/generators/component/lib/utils.ts index 1864103e5fb73..ce1c9407889c1 100644 --- a/packages/vue/src/generators/component/lib/utils.ts +++ b/packages/vue/src/generators/component/lib/utils.ts @@ -6,8 +6,11 @@ import { names, Tree, } from '@nx/devkit'; -import { NormalizedSchema, Schema } from '../schema'; +import { parse, relative, dirname } from 'path'; import { ensureTypescript } from '@nx/js/src/utils/typescript/ensure-typescript'; +import { determineArtifactNameAndDirectoryOptions } from '@nx/devkit/src/generators/artifact-name-and-directory-utils'; + +import { NormalizedSchema, Schema } from '../schema'; import { addImport } from '../../../utils/ast-utils'; let tsModule: typeof import('typescript'); @@ -18,21 +21,31 @@ export async function normalizeOptions( ): Promise { assertValidOptions(options); - const { className, fileName } = names(options.name); - const componentFileName = - options.fileName ?? (options.pascalCaseFiles ? className : fileName); - const project = getProjects(host).get(options.project); - - if (!project) { - throw new Error( - `Cannot find the ${options.project} project. Please double check the project name.` - ); - } + const { + artifactName: name, + directory, + fileName, + filePath, + project: projectName, + } = await determineArtifactNameAndDirectoryOptions(host, { + artifactType: 'component', + callingGenerator: '@nx/vue:component', + name: options.name, + directory: options.directory, + derivedDirectory: options.directory, + flat: options.flat, + nameAndDirectoryFormat: options.nameAndDirectoryFormat, + project: options.project, + fileExtension: 'vue', + pascalCaseFile: options.pascalCaseFiles, + pascalCaseDirectory: options.pascalCaseDirectory, + }); + let { className } = names(fileName); + const componentFileName = fileName; + const project = getProjects(host).get(projectName); const { sourceRoot: projectSourceRoot, projectType } = project; - const directory = await getDirectory(options); - if (options.export && projectType === 'application') { logger.warn( `The "--export" option should not be used with applications and will do nothing.` @@ -44,6 +57,7 @@ export async function normalizeOptions( return { ...options, + filePath, directory, className, fileName: componentFileName, @@ -71,11 +85,16 @@ export function addExportsToBarrel(host: Tree, options: NormalizedSchema) { tsModule.ScriptTarget.Latest, true ); + + const relativePathFromIndex = getRelativeImportToFile( + indexFilePath, + options.filePath + ); const changes = applyChangesToString( indexSource, addImport( indexSourceFile, - `export { default as ${options.className} } from './${options.directory}/${options.fileName}.vue';` + `export { default as ${options.className} } from '${relativePathFromIndex}';` ) ); host.write(indexFilePath, changes); @@ -83,12 +102,10 @@ export function addExportsToBarrel(host: Tree, options: NormalizedSchema) { } } -export async function getDirectory(options: Schema) { - if (options.directory) return options.directory; - if (options.flat) return 'components'; - const { className, fileName } = names(options.name); - const nestedDir = options.pascalCaseDirectory === true ? className : fileName; - return joinPathFragments('components', nestedDir); +function getRelativeImportToFile(indexPath: string, filePath: string) { + const { base, dir } = parse(filePath); + const relativeDirToTarget = relative(dirname(indexPath), dir); + return `./${joinPathFragments(relativeDirToTarget, base)}`; } export function assertValidOptions(options: Schema) { diff --git a/packages/vue/src/generators/component/schema.d.ts b/packages/vue/src/generators/component/schema.d.ts index 42cae02cd4f3c..ed24fc3272a96 100644 --- a/packages/vue/src/generators/component/schema.d.ts +++ b/packages/vue/src/generators/component/schema.d.ts @@ -1,22 +1,37 @@ export interface Schema { name: string; - project: string; skipTests?: boolean; directory?: string; export?: boolean; - pascalCaseFiles?: boolean; - pascalCaseDirectory?: boolean; routing?: boolean; js?: boolean; - flat?: boolean; fileName?: string; inSourceTests?: boolean; skipFormat?: boolean; unitTestRunner?: 'jest' | 'vitest' | 'none'; + nameAndDirectoryFormat?: 'as-provided' | 'derived'; + + /** + * @deprecated Provide the `directory` option instead and use the `as-provided` format. It will be removed in Nx v18. + */ + flat?: boolean; + /** + * @deprecated Provide the desired `directory` option instead and use the `as-provided` format. It will be removed in Nx v18. + */ + pascalCaseDirectory?: boolean; + /** + * @deprecated Provide the desired `name` option instead and use the `as-provided` format. It will be removed in Nx v18. + */ + pascalCaseFiles?: boolean; + /** + * @deprecated Provide the `directory` option instead. The project will be determined from the directory provided. It will be removed in Nx v18. + */ + project?: string; } export interface NormalizedSchema extends Schema { projectSourceRoot: string; fileName: string; className: string; + filePath: string; } diff --git a/packages/vue/src/generators/component/schema.json b/packages/vue/src/generators/component/schema.json index 27a4305b95995..daa4f3cb4de0b 100644 --- a/packages/vue/src/generators/component/schema.json +++ b/packages/vue/src/generators/component/schema.json @@ -23,8 +23,7 @@ "$default": { "$source": "projectName" }, - "x-prompt": "What is the name of the project for this component?", - "x-priority": "important" + "x-deprecated": "Provide the `directory` option instead and use the `as-provided` format. The project will be determined from the directory provided. It will be removed in Nx v18." }, "name": { "type": "string", @@ -36,6 +35,11 @@ "x-prompt": "What name would you like to use for the component?", "x-priority": "important" }, + "nameAndDirectoryFormat": { + "description": "Whether to generate the component in the directory as provided, relative to the current working directory and ignoring the project (`as-provided`) or generate it using the project and directory relative to the workspace root (`derived`).", + "type": "string", + "enum": ["as-provided", "derived"] + }, "js": { "type": "boolean", "description": "Generate JavaScript files rather than TypeScript files.", @@ -49,14 +53,15 @@ }, "directory": { "type": "string", - "description": "Create the component under this directory (can be nested).", + "description": "The directory at which to create the component file. When `--nameAndDirectoryFormat=as-provided`, it will be relative to the current working directory. Otherwise, it will be relative to the workspace root.", "alias": "dir", "x-priority": "important" }, "flat": { "type": "boolean", "description": "Create component at the source root rather than its own directory.", - "default": false + "default": false, + "x-deprecated": "Provide the `directory` option instead and use the `as-provided` format. It will be removed in Nx v18." }, "export": { "type": "boolean", @@ -69,13 +74,15 @@ "type": "boolean", "description": "Use pascal case component file name (e.g. `App.tsx`).", "alias": "P", - "default": false + "default": false, + "x-deprecated": "Provide the desired `name` option instead and use the `as-provided` format. It will be removed in Nx v18." }, "pascalCaseDirectory": { "type": "boolean", "description": "Use pascal case directory name (e.g. `App/App.tsx`).", "alias": "R", - "default": false + "default": false, + "x-deprecated": "Provide the desired `directory` option instead and use the `as-provided` format. It will be removed in Nx v18." }, "routing": { "type": "boolean", @@ -103,5 +110,5 @@ "x-prompt": "What unit test runner should be used?" } }, - "required": ["name", "project"] + "required": ["name"] } diff --git a/packages/vue/src/generators/library/library.spec.ts b/packages/vue/src/generators/library/library.spec.ts index 2713f20d5e7a8..01d0e0c4df0a7 100644 --- a/packages/vue/src/generators/library/library.spec.ts +++ b/packages/vue/src/generators/library/library.spec.ts @@ -162,8 +162,8 @@ describe('lib', () => { await libraryGenerator(tree, defaultSchema); expect(tree.exists('my-lib/package.json')).toBeFalsy(); expect(tree.exists('my-lib/src/index.ts')).toBeTruthy(); - expect(tree.exists('my-lib/src/components/my-lib.vue')).toBeTruthy(); - expect(tree.exists('my-lib/src/components/my-lib.spec.ts')).toBeTruthy(); + expect(tree.exists('my-lib/src/lib/my-lib.vue')).toBeTruthy(); + expect(tree.exists('my-lib/src/lib/my-lib.spec.ts')).toBeTruthy(); const eslintJson = readJson(tree, 'my-lib/.eslintrc.json'); expect(eslintJson).toMatchSnapshot(); }); @@ -201,10 +201,10 @@ describe('lib', () => { await libraryGenerator(tree, { ...defaultSchema, directory: 'myDir' }); expect(tree.exists('my-dir/my-lib/src/index.ts')).toBeTruthy(); expect( - tree.exists('my-dir/my-lib/src/components/my-dir-my-lib.vue') + tree.exists('my-dir/my-lib/src/lib/my-dir-my-lib.vue') ).toBeTruthy(); expect( - tree.exists('my-dir/my-lib/src/components/my-dir-my-lib.spec.ts') + tree.exists('my-dir/my-lib/src/lib/my-dir-my-lib.spec.ts') ).toBeTruthy(); }); diff --git a/packages/vue/src/generators/library/library.ts b/packages/vue/src/generators/library/library.ts index 78a755e37dec1..7e76b6ba22d63 100644 --- a/packages/vue/src/generators/library/library.ts +++ b/packages/vue/src/generators/library/library.ts @@ -56,23 +56,20 @@ export async function libraryGenerator(tree: Tree, schema: Schema) { tasks.push(await addJest(tree, options)); if (options.component) { - tasks.push( - await componentGenerator(tree, { - name: options.name, - project: options.name, - flat: true, - skipTests: - options.unitTestRunner === 'none' || - (options.unitTestRunner === 'vitest' && - options.inSourceTests == true), - export: true, - routing: options.routing, - js: options.js, - pascalCaseFiles: options.pascalCaseFiles, - inSourceTests: options.inSourceTests, - skipFormat: true, - }) - ); + await componentGenerator(tree, { + name: options.name, + project: options.name, + flat: true, + skipTests: + options.unitTestRunner === 'none' || + (options.unitTestRunner === 'vitest' && options.inSourceTests == true), + export: true, + routing: options.routing, + js: options.js, + pascalCaseFiles: options.pascalCaseFiles, + inSourceTests: options.inSourceTests, + skipFormat: true, + }); } if (options.publishable || options.bundler !== 'none') { diff --git a/packages/vue/src/generators/stories/lib/component-story.spec.ts b/packages/vue/src/generators/stories/lib/component-story.spec.ts index 6e68c1cb07e9d..3d332912ad69d 100644 --- a/packages/vue/src/generators/stories/lib/component-story.spec.ts +++ b/packages/vue/src/generators/stories/lib/component-story.spec.ts @@ -6,8 +6,8 @@ import { Linter } from '@nx/eslint'; describe('vue:component-story', () => { let appTree: Tree; - let cmpPath = 'test-ui-lib/src/components/test-ui-lib.vue'; - let storyFilePath = 'test-ui-lib/src/components/test-ui-lib.stories.ts'; + let cmpPath = 'test-ui-lib/src/lib/test-ui-lib.vue'; + let storyFilePath = 'test-ui-lib/src/lib/test-ui-lib.stories.ts'; describe('default setup', () => { beforeEach(async () => { @@ -22,7 +22,7 @@ describe('vue:component-story', () => { interactionTests: true, project: 'test-ui-lib', }, - 'components/test-ui-lib.vue' + 'lib/test-ui-lib.vue' ); }); @@ -58,7 +58,7 @@ describe('vue:component-story', () => { interactionTests: true, project: 'test-ui-lib', }, - 'components/test-ui-lib.vue' + 'lib/test-ui-lib.vue' ); }); @@ -97,7 +97,7 @@ describe('vue:component-story', () => { interactionTests: true, project: 'test-ui-lib', }, - 'components/test-ui-lib.vue' + 'lib/test-ui-lib.vue' ); }); diff --git a/packages/vue/src/generators/stories/stories.app.spec.ts b/packages/vue/src/generators/stories/stories.app.spec.ts index dded11aaa60fd..cead472d3001c 100644 --- a/packages/vue/src/generators/stories/stories.app.spec.ts +++ b/packages/vue/src/generators/stories/stories.app.spec.ts @@ -28,7 +28,7 @@ describe('vue:stories for applications', () => { // create another component appTree.write( - 'test-ui-app/src/components/another-cmp/another-cmp.vue', + 'test-ui-app/src/app/another-cmp/another-cmp.vue', componentContent ); }); @@ -43,7 +43,7 @@ describe('vue:stories for applications', () => { ).toMatchSnapshot(); expect( appTree.read( - 'test-ui-app/src/components/another-cmp/another-cmp.stories.ts', + 'test-ui-app/src/app/another-cmp/another-cmp.stories.ts', 'utf-8' ) ).toMatchSnapshot(); @@ -60,7 +60,7 @@ describe('vue:stories for applications', () => { ).toMatchSnapshot(); expect( appTree.read( - 'test-ui-app/src/components/another-cmp/another-cmp.stories.ts', + 'test-ui-app/src/app/another-cmp/another-cmp.stories.ts', 'utf-8' ) ).toMatchSnapshot(); @@ -84,12 +84,12 @@ describe('vue:stories for applications', () => { describe('ignore paths', () => { beforeEach(() => { appTree.write( - 'test-ui-app/src/components/test-path/ignore-it/another-one.vue', + 'test-ui-app/src/app/test-path/ignore-it/another-one.vue', componentContent ); appTree.write( - 'test-ui-app/src/components/another-cmp/another-cmp-test.skip.vue', + 'test-ui-app/src/app/another-cmp/another-cmp-test.skip.vue', componentContent ); }); @@ -102,20 +102,18 @@ describe('vue:stories for applications', () => { appTree.exists('test-ui-app/src/app/NxWelcome.stories.ts') ).toBeTruthy(); expect( - appTree.exists( - 'test-ui-app/src/components/another-cmp/another-cmp.stories.ts' - ) + appTree.exists('test-ui-app/src/app/another-cmp/another-cmp.stories.ts') ).toBeTruthy(); expect( appTree.exists( - 'test-ui-app/src/components/test-path/ignore-it/another-one.stories.ts' + 'test-ui-app/src/app/test-path/ignore-it/another-one.stories.ts' ) ).toBeTruthy(); expect( appTree.exists( - 'test-ui-app/src/components/another-cmp/another-cmp-test.skip.stories.ts' + 'test-ui-app/src/app/another-cmp/another-cmp-test.skip.stories.ts' ) ).toBeTruthy(); }); @@ -124,7 +122,7 @@ describe('vue:stories for applications', () => { await storiesGenerator(appTree, { project: 'test-ui-app', ignorePaths: [ - `test-ui-app/src/components/another-cmp/**`, + `test-ui-app/src/app/another-cmp/**`, `**/**/src/**/test-path/ignore-it/**`, ], }); @@ -133,20 +131,18 @@ describe('vue:stories for applications', () => { appTree.exists('test-ui-app/src/app/NxWelcome.stories.ts') ).toBeTruthy(); expect( - appTree.exists( - 'test-ui-app/src/components/another-cmp/another-cmp.stories.ts' - ) + appTree.exists('test-ui-app/src/app/another-cmp/another-cmp.stories.ts') ).toBeFalsy(); expect( appTree.exists( - 'test-ui-app/src/components/test-path/ignore-it/another-one.stories.ts' + 'test-ui-app/src/app/test-path/ignore-it/another-one.stories.ts' ) ).toBeFalsy(); expect( appTree.exists( - 'test-ui-app/src/components/another-cmp/another-cmp-test.skip.stories.ts' + 'test-ui-app/src/app/another-cmp/another-cmp-test.skip.stories.ts' ) ).toBeFalsy(); }); @@ -155,7 +151,7 @@ describe('vue:stories for applications', () => { await storiesGenerator(appTree, { project: 'test-ui-app', ignorePaths: [ - 'test-ui-app/src/components/another-cmp/**/*.skip.*', + 'test-ui-app/src/app/another-cmp/**/*.skip.*', '**/**/src/**/test-path/**', ], }); @@ -164,20 +160,18 @@ describe('vue:stories for applications', () => { appTree.exists('test-ui-app/src/app/NxWelcome.stories.ts') ).toBeTruthy(); expect( - appTree.exists( - 'test-ui-app/src/components/another-cmp/another-cmp.stories.ts' - ) + appTree.exists('test-ui-app/src/app/another-cmp/another-cmp.stories.ts') ).toBeTruthy(); expect( appTree.exists( - 'test-ui-app/src/components/test-path/ignore-it/another-one.stories.ts' + 'test-ui-app/src/app/test-path/ignore-it/another-one.stories.ts' ) ).toBeFalsy(); expect( appTree.exists( - 'test-ui-app/src/components/another-cmp/another-cmp-test.skip.stories.ts' + 'test-ui-app/src/app/another-cmp/another-cmp-test.skip.stories.ts' ) ).toBeFalsy(); }); @@ -185,41 +179,39 @@ describe('vue:stories for applications', () => { it('should ignore direct path to component', async () => { await storiesGenerator(appTree, { project: 'test-ui-app', - ignorePaths: ['test-ui-app/src/components/another-cmp/**/*.skip.vue'], + ignorePaths: ['test-ui-app/src/app/another-cmp/**/*.skip.vue'], }); expect( appTree.exists('test-ui-app/src/app/NxWelcome.stories.ts') ).toBeTruthy(); expect( - appTree.exists( - 'test-ui-app/src/components/another-cmp/another-cmp.stories.ts' - ) + appTree.exists('test-ui-app/src/app/another-cmp/another-cmp.stories.ts') ).toBeTruthy(); expect( appTree.exists( - 'test-ui-app/src/components/test-path/ignore-it/another-one.stories.ts' + 'test-ui-app/src/app/test-path/ignore-it/another-one.stories.ts' ) ).toBeTruthy(); expect( appTree.exists( - 'test-ui-app/src/components/another-cmp/another-cmp-test.skip.stories.ts' + 'test-ui-app/src/app/another-cmp/another-cmp-test.skip.stories.ts' ) ).toBeFalsy(); }); it('should ignore a path that has a nested component, but still generate nested component stories', async () => { appTree.write( - 'test-ui-app/src/components/another-cmp/comp-a/comp-a.vue', + 'test-ui-app/src/app/another-cmp/comp-a/comp-a.vue', componentContent ); await storiesGenerator(appTree, { project: 'test-ui-app', ignorePaths: [ - 'test-ui-app/src/components/another-cmp/another-cmp-test.skip.vue', + 'test-ui-app/src/app/another-cmp/another-cmp-test.skip.vue', ], }); @@ -227,20 +219,18 @@ describe('vue:stories for applications', () => { appTree.exists('test-ui-app/src/app/NxWelcome.stories.ts') ).toBeTruthy(); expect( - appTree.exists( - 'test-ui-app/src/components/another-cmp/another-cmp.stories.ts' - ) + appTree.exists('test-ui-app/src/app/another-cmp/another-cmp.stories.ts') ).toBeTruthy(); expect( appTree.exists( - 'test-ui-app/src/components/another-cmp/comp-a/comp-a.stories.ts' + 'test-ui-app/src/app/another-cmp/comp-a/comp-a.stories.ts' ) ).toBeTruthy(); expect( appTree.exists( - 'test-ui-app/src/components/another-cmp/another-cmp-test.skip.stories.ts' + 'test-ui-app/src/app/another-cmp/another-cmp-test.skip.stories.ts' ) ).toBeFalsy(); }); diff --git a/packages/vue/src/generators/stories/stories.lib.spec.ts b/packages/vue/src/generators/stories/stories.lib.spec.ts index 55cf9a5ac02f9..99960d0ca3d53 100644 --- a/packages/vue/src/generators/stories/stories.lib.spec.ts +++ b/packages/vue/src/generators/stories/stories.lib.spec.ts @@ -26,7 +26,7 @@ describe('vue:stories for libraries', () => { beforeEach(async () => { appTree = await createTestUILib('test-ui-lib'); appTree.write( - 'test-ui-lib/src/components/another-cmp/another-cmp.vue', + 'test-ui-lib/src/lib/another-cmp/another-cmp.vue', componentContent ); }); @@ -37,11 +37,11 @@ describe('vue:stories for libraries', () => { }); expect( - appTree.read('test-ui-lib/src/components/test-ui-lib.stories.ts', 'utf-8') + appTree.read('test-ui-lib/src/lib/test-ui-lib.stories.ts', 'utf-8') ).toMatchSnapshot(); expect( appTree.read( - 'test-ui-lib/src/components/another-cmp/another-cmp.stories.ts', + 'test-ui-lib/src/lib/another-cmp/another-cmp.stories.ts', 'utf-8' ) ).toMatchSnapshot(); @@ -62,11 +62,11 @@ describe('vue:stories for libraries', () => { interactionTests: false, }); expect( - appTree.read('test-ui-lib/src/components/test-ui-lib.stories.ts', 'utf-8') + appTree.read('test-ui-lib/src/lib/test-ui-lib.stories.ts', 'utf-8') ).toMatchSnapshot(); expect( appTree.read( - 'test-ui-lib/src/components/another-cmp/another-cmp.stories.ts', + 'test-ui-lib/src/lib/another-cmp/another-cmp.stories.ts', 'utf-8' ) ).toMatchSnapshot(); @@ -85,12 +85,12 @@ describe('vue:stories for libraries', () => { describe('ignore paths', () => { beforeEach(() => { appTree.write( - 'test-ui-lib/src/components/test-path/ignore-it/another-one.vue', + 'test-ui-lib/src/lib/test-path/ignore-it/another-one.vue', componentContent ); appTree.write( - 'test-ui-lib/src/components/another-cmp/another-cmp.skip.vue', + 'test-ui-lib/src/lib/another-cmp/another-cmp.skip.vue', componentContent ); }); @@ -100,20 +100,18 @@ describe('vue:stories for libraries', () => { }); expect( - appTree.exists( - 'test-ui-lib/src/components/another-cmp/another-cmp.stories.ts' - ) + appTree.exists('test-ui-lib/src/lib/another-cmp/another-cmp.stories.ts') ).toBeTruthy(); expect( appTree.exists( - 'test-ui-lib/src/components/test-path/ignore-it/another-one.stories.ts' + 'test-ui-lib/src/lib/test-path/ignore-it/another-one.stories.ts' ) ).toBeTruthy(); expect( appTree.exists( - 'test-ui-lib/src/components/another-cmp/another-cmp.skip.stories.ts' + 'test-ui-lib/src/lib/another-cmp/another-cmp.skip.stories.ts' ) ).toBeTruthy(); }); @@ -122,26 +120,24 @@ describe('vue:stories for libraries', () => { await storiesGenerator(appTree, { project: 'test-ui-lib', ignorePaths: [ - 'test-ui-lib/src/components/another-cmp/**', + 'test-ui-lib/src/lib/another-cmp/**', '**/**/src/**/test-path/ignore-it/**', ], }); expect( - appTree.exists( - 'test-ui-lib/src/components/another-cmp/another-cmp.stories.ts' - ) + appTree.exists('test-ui-lib/src/lib/another-cmp/another-cmp.stories.ts') ).toBeFalsy(); expect( appTree.exists( - 'test-ui-lib/src/components/test-path/ignore-it/another-one.stories.ts' + 'test-ui-lib/src/lib/test-path/ignore-it/another-one.stories.ts' ) ).toBeFalsy(); expect( appTree.exists( - 'test-ui-lib/src/components/another-cmp/another-cmp.skip.stories.ts' + 'test-ui-lib/src/lib/another-cmp/another-cmp.skip.stories.ts' ) ).toBeFalsy(); }); @@ -150,26 +146,24 @@ describe('vue:stories for libraries', () => { await storiesGenerator(appTree, { project: 'test-ui-lib', ignorePaths: [ - 'test-ui-lib/src/components/another-cmp/**/*.skip.*', + 'test-ui-lib/src/lib/another-cmp/**/*.skip.*', '**/test-ui-lib/src/**/test-path/**', ], }); expect( - appTree.exists( - 'test-ui-lib/src/components/another-cmp/another-cmp.stories.ts' - ) + appTree.exists('test-ui-lib/src/lib/another-cmp/another-cmp.stories.ts') ).toBeTruthy(); expect( appTree.exists( - 'test-ui-lib/src/components/test-path/ignore-it/another-one.stories.ts' + 'test-ui-lib/src/lib/test-path/ignore-it/another-one.stories.ts' ) ).toBeFalsy(); expect( appTree.exists( - 'test-ui-lib/src/components/another-cmp/another-cmp.skip.stories.ts' + 'test-ui-lib/src/lib/another-cmp/another-cmp.skip.stories.ts' ) ).toBeFalsy(); }); diff --git a/packages/vue/src/generators/stories/stories.ts b/packages/vue/src/generators/stories/stories.ts index c9bb3149c8609..97132d1557e08 100644 --- a/packages/vue/src/generators/stories/stories.ts +++ b/packages/vue/src/generators/stories/stories.ts @@ -37,7 +37,8 @@ export async function createAllStories( let componentPaths: string[] = []; const pathsToCheck = [ joinPathFragments(sourceRoot, 'app'), // Default component folder for apps - joinPathFragments(sourceRoot, 'components'), // Additional component folder + joinPathFragments(sourceRoot, 'lib'), // Default component folder for libs + joinPathFragments(sourceRoot, 'components'), // Additional component folder used by Nuxt ]; for (const p of pathsToCheck) { diff --git a/packages/vue/src/generators/storybook-configuration/configuration.spec.ts b/packages/vue/src/generators/storybook-configuration/configuration.spec.ts index a01eb66673b06..06585122157db 100644 --- a/packages/vue/src/generators/storybook-configuration/configuration.spec.ts +++ b/packages/vue/src/generators/storybook-configuration/configuration.spec.ts @@ -67,7 +67,7 @@ describe('vue:storybook-configuration', () => { it('should generate stories for components', async () => { appTree = await createTestUILib('test-ui-lib'); appTree.write( - 'test-ui-lib/src/components/my-component/my-component.vue', + 'test-ui-lib/src/lib/my-component/my-component.vue', componentContent ); @@ -77,11 +77,11 @@ describe('vue:storybook-configuration', () => { }); expect( - appTree.exists('test-ui-lib/src/components/test-ui-lib.stories.ts') + appTree.exists('test-ui-lib/src/lib/test-ui-lib.stories.ts') ).toBeTruthy(); expect( appTree.read( - 'test-ui-lib/src/components/my-component/my-component.stories.ts', + 'test-ui-lib/src/lib/my-component/my-component.stories.ts', 'utf-8' ) ).toMatchSnapshot(); @@ -100,7 +100,7 @@ describe('vue:storybook-configuration', () => { it('should generate stories for components for app', async () => { appTree = await createTestAppLib('test-ui-app'); appTree.write( - 'test-ui-app/src/components/my-component/my-component.vue', + 'test-ui-app/src/app/my-component/my-component.vue', componentContent ); await storybookConfigurationGenerator(appTree, { @@ -110,7 +110,7 @@ describe('vue:storybook-configuration', () => { expect( appTree.read( - 'test-ui-app/src/components/my-component/my-component.stories.ts', + 'test-ui-app/src/app/my-component/my-component.stories.ts', 'utf-8' ) ).toMatchSnapshot(); @@ -119,7 +119,7 @@ describe('vue:storybook-configuration', () => { it('should generate stories for components without interaction tests', async () => { appTree = await createTestAppLib('test-ui-app'); appTree.write( - 'test-ui-app/src/components/my-component/my-component.vue', + 'test-ui-app/src/app/my-component/my-component.vue', componentContent ); await storybookConfigurationGenerator(appTree, { @@ -130,7 +130,7 @@ describe('vue:storybook-configuration', () => { expect( appTree.read( - 'test-ui-app/src/components/my-component/my-component.stories.ts', + 'test-ui-app/src/app/my-component/my-component.stories.ts', 'utf-8' ) ).toMatchSnapshot();