Nuxt/packages/nuxt/test/scan-components.test.ts
Aleksandar Trpkovski 00917a1bd8
feat(nuxt): scan and register layouts in nested folders (#20190)
Co-authored-by: Daniel Roe <daniel@roe.dev>
2023-10-16 22:58:40 +01:00

273 lines
6.8 KiB
TypeScript

import { resolve } from 'node:path'
import { describe, expect, it, vi } from 'vitest'
import type { ComponentsDir } from 'nuxt/schema'
import { scanComponents } from '../src/components/scan'
import { resolveComponentName } from '../src/core/utils'
const fixtureDir = resolve(__dirname, 'fixture')
const rFixture = (...p: string[]) => resolve(fixtureDir, ...p)
vi.mock('@nuxt/kit', () => ({
isIgnored: () => false
}))
const dirs: ComponentsDir[] = [
{
path: rFixture('components/islands'),
enabled: true,
extensions: [
'vue'
],
pattern: '**/*.{vue,}',
ignore: [
'**/*.stories.{js,ts,jsx,tsx}',
'**/*{M,.m,-m}ixin.{js,ts,jsx,tsx}',
'**/*.d.ts'
],
transpile: false,
island: true
},
{
path: rFixture('components/global'),
enabled: true,
extensions: [
'vue'
],
pattern: '**/*.{vue,}',
ignore: [
'**/*.stories.{js,ts,jsx,tsx}',
'**/*{M,.m,-m}ixin.{js,ts,jsx,tsx}',
'**/*.d.ts'
],
transpile: false,
global: true
},
{
path: rFixture('components'),
enabled: true,
extensions: [
'vue'
],
pattern: '**/*.{vue,}',
ignore: [
'**/*.stories.{js,ts,jsx,tsx}',
'**/*{M,.m,-m}ixin.{js,ts,jsx,tsx}',
'**/*.d.ts'
],
transpile: false
},
{
path: rFixture('components'),
enabled: true,
extensions: [
'vue'
],
pattern: '**/*.{vue,}',
ignore: [
'**/*.stories.{js,ts,jsx,tsx}',
'**/*{M,.m,-m}ixin.{js,ts,jsx,tsx}',
'**/*.d.ts'
],
transpile: false
},
{
path: rFixture('components'),
extensions: [
'vue'
],
prefix: 'nuxt',
enabled: true,
pattern: '**/*.{vue,}',
ignore: [
'**/*.stories.{js,ts,jsx,tsx}',
'**/*{M,.m,-m}ixin.{js,ts,jsx,tsx}',
'**/*.d.ts'
],
transpile: false
}
]
const expectedComponents = [
{
chunkName: 'components/isle-server',
export: 'default',
global: undefined,
island: true,
kebabName: 'isle',
mode: 'server',
pascalName: 'Isle',
prefetch: false,
preload: false,
priority: 1,
shortPath: 'components/islands/Isle.vue'
},
{
chunkName: 'components/glob',
export: 'default',
global: true,
island: undefined,
kebabName: 'glob',
mode: 'all',
pascalName: 'Glob',
prefetch: false,
preload: false,
priority: 1,
shortPath: 'components/global/Glob.vue'
},
{
mode: 'all',
pascalName: 'HelloWorld',
kebabName: 'hello-world',
chunkName: 'components/hello-world',
shortPath: 'components/HelloWorld.vue',
export: 'default',
global: undefined,
island: undefined,
prefetch: false,
preload: false,
priority: 1
},
{
mode: 'client',
pascalName: 'Nuxt3',
kebabName: 'nuxt3',
chunkName: 'components/nuxt3-client',
shortPath: 'components/Nuxt3.client.vue',
export: 'default',
global: undefined,
island: undefined,
prefetch: false,
preload: false,
priority: 1
},
{
mode: 'server',
pascalName: 'Nuxt3',
kebabName: 'nuxt3',
chunkName: 'components/nuxt3-server',
shortPath: 'components/Nuxt3.server.vue',
export: 'default',
global: undefined,
island: undefined,
prefetch: false,
preload: false,
priority: 1
},
{
chunkName: 'components/client-component-with-props',
export: 'default',
global: undefined,
island: undefined,
kebabName: 'client-component-with-props',
mode: 'all',
pascalName: 'ClientComponentWithProps',
prefetch: false,
preload: false,
priority: 1,
shortPath: 'components/client/ComponentWithProps.vue'
},
{
chunkName: 'components/client-with-client-only-setup',
export: 'default',
global: undefined,
island: undefined,
kebabName: 'client-with-client-only-setup',
mode: 'all',
pascalName: 'ClientWithClientOnlySetup',
prefetch: false,
preload: false,
priority: 1,
shortPath: 'components/client/WithClientOnlySetup.vue'
},
{
mode: 'server',
pascalName: 'ParentFolder',
kebabName: 'parent-folder',
chunkName: 'components/parent-folder-server',
shortPath: 'components/parent-folder/index.server.vue',
export: 'default',
global: undefined,
island: undefined,
prefetch: false,
preload: false,
priority: 1
},
{
chunkName: 'components/same-name-same',
export: 'default',
global: undefined,
island: undefined,
kebabName: 'same-name-same',
mode: 'all',
pascalName: 'SameNameSame',
prefetch: false,
preload: false,
priority: 1,
shortPath: 'components/same-name/same/Same.vue'
},
{
chunkName: 'components/some-glob',
export: 'default',
global: true,
island: undefined,
kebabName: 'some-glob',
mode: 'all',
pascalName: 'SomeGlob',
prefetch: false,
preload: false,
priority: 1,
shortPath: 'components/some-glob.global.vue'
},
{
chunkName: 'components/some-server',
export: 'default',
global: undefined,
island: true,
kebabName: 'some',
mode: 'server',
pascalName: 'Some',
prefetch: false,
preload: false,
priority: 1,
shortPath: 'components/some.island.vue'
}
]
const srcDir = rFixture('.')
it('components:scanComponents', async () => {
const scannedComponents = await scanComponents(dirs, srcDir)
for (const c of scannedComponents) {
// @ts-expect-error filePath is not optional but we don't want it to be in the snapshot
delete c.filePath
}
expect(scannedComponents).deep.eq(expectedComponents)
})
const tests: Array<[string, string[], string]> = [
['WithClientOnlySetup', ['Client'], 'ClientWithClientOnlySetup'],
['ItemHolderItem', ['Item', 'Holder', 'Item'], 'ItemHolderItem'],
['Item', ['Item'], 'Item'],
['Item', ['Item', 'Item'], 'Item'],
['ItemTest', ['Item', 'Test'], 'ItemTest'],
['ThingItemTest', ['Item', 'Thing'], 'ItemThingItemTest'],
['Item', ['Thing', 'Item'], 'ThingItem'],
['Item', ['Item', 'Holder', 'Item'], 'ItemHolderItem'],
['ItemHolder', ['Item', 'Holder', 'Item'], 'ItemHolderItemHolder'],
['ThingItemTest', ['Item', 'Thing', 'Foo'], 'ItemThingFooThingItemTest'],
['ItemIn', ['Item', 'Holder', 'Item', 'In'], 'ItemHolderItemIn'],
['Item', ['Item', 'Holder', 'Test'], 'ItemHolderTestItem'],
['ItemHolderItem', ['Item', 'Holder', 'Item', 'Holder'], 'ItemHolderItemHolderItem'],
['Icones', ['Icon'], 'IconIcones'],
['Icon', ['Icones'], 'IconesIcon'],
['IconHolder', ['IconHolder'], 'IconHolder'],
['GameList', ['Desktop', 'ShareGame', 'Review', 'Detail'], 'DesktopShareGameReviewDetailGameList']
]
describe('components:resolveComponentName', () => {
it.each(tests)('resolves %s with prefix parts %s and filename %s', (fileName, prefixParts: string[], result) => {
expect(resolveComponentName(fileName, prefixParts)).toBe(result)
})
})