2022-04-15 15:19:05 +00:00
|
|
|
import { readFileSync } from 'node:fs'
|
2024-06-15 23:03:24 +00:00
|
|
|
import { fileURLToPath } from 'node:url'
|
2023-04-07 16:02:47 +00:00
|
|
|
import { describe, expect, it } from 'vitest'
|
2024-06-15 23:03:24 +00:00
|
|
|
import { findExports } from 'mlly'
|
2021-11-05 14:39:14 +00:00
|
|
|
import * as VueFunctions from 'vue'
|
2022-12-11 21:44:52 +00:00
|
|
|
import type { Import } from 'unimport'
|
|
|
|
import { createUnimport } from 'unimport'
|
|
|
|
import type { Plugin } from 'vite'
|
2024-06-11 09:14:11 +00:00
|
|
|
import { registry as scriptRegistry } from '@nuxt/scripts/registry'
|
2022-08-23 14:22:11 +00:00
|
|
|
import { TransformPlugin } from '../src/imports/transform'
|
2024-06-11 09:14:11 +00:00
|
|
|
import { defaultPresets, scriptsStubsPreset } from '../src/imports/presets'
|
2021-08-10 00:27:23 +00:00
|
|
|
|
2022-08-23 14:22:11 +00:00
|
|
|
describe('imports:transform', () => {
|
2022-03-11 08:09:11 +00:00
|
|
|
const imports: Import[] = [
|
2021-10-18 13:39:53 +00:00
|
|
|
{ name: 'ref', as: 'ref', from: 'vue' },
|
2021-12-21 14:28:45 +00:00
|
|
|
{ name: 'computed', as: 'computed', from: 'bar' },
|
2024-04-05 18:08:32 +00:00
|
|
|
{ name: 'foo', as: 'foo', from: 'excluded' },
|
2021-10-18 13:39:53 +00:00
|
|
|
]
|
|
|
|
|
2022-03-11 08:09:11 +00:00
|
|
|
const ctx = createUnimport({
|
2024-04-05 18:08:32 +00:00
|
|
|
imports,
|
2022-03-11 08:09:11 +00:00
|
|
|
})
|
2021-10-20 09:47:18 +00:00
|
|
|
|
2022-10-18 09:36:06 +00:00
|
|
|
const transformPlugin = TransformPlugin.raw({ ctx, options: { transform: { exclude: [/node_modules/] } } }, { framework: 'rollup' }) as Plugin
|
2022-03-11 08:09:11 +00:00
|
|
|
const transform = async (source: string) => {
|
2024-08-06 14:16:20 +00:00
|
|
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
|
2022-10-18 09:36:06 +00:00
|
|
|
const result = await (transformPlugin.transform! as Function).call({ error: null, warn: null } as any, source, '')
|
2022-08-22 10:12:02 +00:00
|
|
|
return typeof result === 'string' ? result : result?.code
|
2022-03-11 08:09:11 +00:00
|
|
|
}
|
2021-08-10 00:27:23 +00:00
|
|
|
|
2021-08-30 11:55:57 +00:00
|
|
|
it('should correct inject', async () => {
|
2022-06-03 14:26:29 +00:00
|
|
|
expect(await transform('const a = ref(0)')).toMatchInlineSnapshot('"import { ref } from \'vue\';\nconst a = ref(0)"')
|
2021-08-10 00:27:23 +00:00
|
|
|
})
|
|
|
|
|
2021-10-12 12:24:43 +00:00
|
|
|
it('should ignore existing imported', async () => {
|
2022-08-22 10:12:02 +00:00
|
|
|
expect(await transform('import { ref } from "foo"; const a = ref(0)')).to.equal(undefined)
|
|
|
|
expect(await transform('import { computed as ref } from "foo"; const a = ref(0)')).to.equal(undefined)
|
|
|
|
expect(await transform('import ref from "foo"; const a = ref(0)')).to.equal(undefined)
|
|
|
|
expect(await transform('import { z as ref } from "foo"; const a = ref(0)')).to.equal(undefined)
|
|
|
|
expect(await transform('let ref = () => {}; const a = ref(0)')).to.equal(undefined)
|
|
|
|
expect(await transform('let { ref } = Vue; const a = ref(0)')).to.equal(undefined)
|
|
|
|
expect(await transform('let [\ncomputed,\nref\n] = Vue; const a = ref(0); const b = ref(0)')).to.equal(undefined)
|
2021-08-30 11:55:57 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
it('should ignore comments', async () => {
|
|
|
|
const result = await transform('// import { computed } from "foo"\n;const a = computed(0)')
|
2022-03-11 08:09:11 +00:00
|
|
|
expect(result).toMatchInlineSnapshot(`
|
2022-06-03 14:26:29 +00:00
|
|
|
"import { computed } from 'bar';
|
2023-12-11 18:20:11 +00:00
|
|
|
// import { computed } from "foo"
|
2022-03-11 08:09:11 +00:00
|
|
|
;const a = computed(0)"
|
|
|
|
`)
|
2021-08-10 00:27:23 +00:00
|
|
|
})
|
2021-12-21 14:28:45 +00:00
|
|
|
|
2022-03-11 08:09:11 +00:00
|
|
|
it('should exclude files from transform', async () => {
|
2022-08-22 10:12:02 +00:00
|
|
|
expect(await transform('excluded')).toEqual(undefined)
|
2021-12-21 14:28:45 +00:00
|
|
|
})
|
2021-08-10 00:27:23 +00:00
|
|
|
})
|
2021-11-05 14:39:14 +00:00
|
|
|
|
2023-03-10 08:01:21 +00:00
|
|
|
const excludedNuxtHelpers = ['useHydration', 'useHead', 'useSeoMeta', 'useServerSeoMeta']
|
2021-12-20 16:27:36 +00:00
|
|
|
|
2022-08-23 14:22:11 +00:00
|
|
|
describe('imports:nuxt', () => {
|
2021-12-20 16:27:36 +00:00
|
|
|
try {
|
2024-06-15 23:03:24 +00:00
|
|
|
const entrypointPath = fileURLToPath(new URL('../src/app/composables/index.ts', import.meta.url))
|
|
|
|
const entrypointContents = readFileSync(entrypointPath, 'utf8')
|
2021-12-20 16:27:36 +00:00
|
|
|
|
|
|
|
const names = findExports(entrypointContents).flatMap(i => i.names || i.name)
|
2023-03-10 08:01:21 +00:00
|
|
|
for (let name of names) {
|
|
|
|
name = name.replace(/\/\*.*\*\//, '').trim()
|
2022-01-21 11:42:41 +00:00
|
|
|
if (excludedNuxtHelpers.includes(name)) {
|
2021-12-20 16:27:36 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
it(`should register ${name} globally`, () => {
|
2023-10-30 21:05:02 +00:00
|
|
|
expect(defaultPresets.flatMap(a => a.from.startsWith('#app/') ? a.imports : [])).to.include(name)
|
2021-12-20 16:27:36 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
} catch (e) {
|
2022-09-21 09:53:38 +00:00
|
|
|
it('should import composables', () => {
|
2023-09-19 21:26:15 +00:00
|
|
|
console.error(e)
|
2022-09-21 09:53:38 +00:00
|
|
|
expect(false).toBe(true)
|
|
|
|
})
|
2021-12-20 16:27:36 +00:00
|
|
|
}
|
|
|
|
})
|
|
|
|
|
2021-11-05 14:39:14 +00:00
|
|
|
const excludedVueHelpers = [
|
2022-02-03 10:21:35 +00:00
|
|
|
// Already globally registered
|
|
|
|
'defineEmits',
|
|
|
|
'defineExpose',
|
|
|
|
'defineProps',
|
|
|
|
'withDefaults',
|
|
|
|
'stop',
|
|
|
|
//
|
2022-01-13 17:54:33 +00:00
|
|
|
'__esModule',
|
|
|
|
'devtools',
|
2021-11-05 14:39:14 +00:00
|
|
|
'EffectScope',
|
|
|
|
'ReactiveEffect',
|
|
|
|
'stop',
|
2023-01-29 14:06:53 +00:00
|
|
|
'assertNumber',
|
2021-11-05 14:39:14 +00:00
|
|
|
'camelize',
|
|
|
|
'capitalize',
|
|
|
|
'normalizeClass',
|
|
|
|
'normalizeProps',
|
|
|
|
'normalizeStyle',
|
|
|
|
'toDisplayString',
|
|
|
|
'toHandlerKey',
|
|
|
|
'BaseTransition',
|
2023-02-06 08:37:46 +00:00
|
|
|
'BaseTransitionPropsValidators',
|
2021-11-05 14:39:14 +00:00
|
|
|
'Comment',
|
|
|
|
'Fragment',
|
|
|
|
'KeepAlive',
|
|
|
|
'Static',
|
|
|
|
'Suspense',
|
|
|
|
'Teleport',
|
|
|
|
'Text',
|
|
|
|
'callWithAsyncErrorHandling',
|
|
|
|
'callWithErrorHandling',
|
|
|
|
'cloneVNode',
|
|
|
|
'compatUtils',
|
|
|
|
'createBlock',
|
|
|
|
'createCommentVNode',
|
|
|
|
'createElementBlock',
|
|
|
|
'createElementVNode',
|
|
|
|
'createHydrationRenderer',
|
|
|
|
'createPropsRestProxy',
|
|
|
|
'createRenderer',
|
|
|
|
'createSlots',
|
|
|
|
'createStaticVNode',
|
|
|
|
'createTextVNode',
|
|
|
|
'createVNode',
|
|
|
|
'getTransitionRawChildren',
|
|
|
|
'guardReactiveProps',
|
|
|
|
'handleError',
|
|
|
|
'initCustomFormatter',
|
|
|
|
'isMemoSame',
|
|
|
|
'isRuntimeOnly',
|
|
|
|
'isVNode',
|
|
|
|
'mergeDefaults',
|
|
|
|
'mergeProps',
|
|
|
|
'openBlock',
|
|
|
|
'popScopeId',
|
|
|
|
'pushScopeId',
|
|
|
|
'queuePostFlushCb',
|
|
|
|
'registerRuntimeCompiler',
|
|
|
|
'renderList',
|
|
|
|
'renderSlot',
|
|
|
|
'resolveComponent',
|
|
|
|
'resolveDirective',
|
|
|
|
'resolveDynamicComponent',
|
|
|
|
'resolveFilter',
|
|
|
|
'resolveTransitionHooks',
|
|
|
|
'setBlockTracking',
|
|
|
|
'setDevtoolsHook',
|
|
|
|
'setTransitionHooks',
|
|
|
|
'ssrContextKey',
|
|
|
|
'ssrUtils',
|
|
|
|
'toHandlers',
|
|
|
|
'transformVNodeArgs',
|
|
|
|
'useSSRContext',
|
|
|
|
'version',
|
|
|
|
'warn',
|
|
|
|
'watchPostEffect',
|
|
|
|
'watchSyncEffect',
|
|
|
|
'withAsyncContext',
|
|
|
|
'Transition',
|
|
|
|
'TransitionGroup',
|
|
|
|
'VueElement',
|
2023-12-20 10:30:33 +00:00
|
|
|
'ErrorTypeStrings',
|
2021-11-05 14:39:14 +00:00
|
|
|
'createApp',
|
|
|
|
'createSSRApp',
|
|
|
|
'defineCustomElement',
|
|
|
|
'defineSSRCustomElement',
|
|
|
|
'hydrate',
|
|
|
|
'initDirectivesForSSR',
|
|
|
|
'render',
|
|
|
|
'useCssVars',
|
|
|
|
'vModelCheckbox',
|
|
|
|
'vModelDynamic',
|
|
|
|
'vModelRadio',
|
|
|
|
'vModelSelect',
|
|
|
|
'vModelText',
|
|
|
|
'vShow',
|
2023-12-29 08:53:46 +00:00
|
|
|
'compile',
|
|
|
|
'DeprecationTypes',
|
|
|
|
'ErrorCodes',
|
|
|
|
'TrackOpTypes',
|
2024-04-05 18:08:32 +00:00
|
|
|
'TriggerOpTypes',
|
2021-11-05 14:39:14 +00:00
|
|
|
]
|
|
|
|
|
2022-08-23 14:22:11 +00:00
|
|
|
describe('imports:vue', () => {
|
2021-11-05 14:39:14 +00:00
|
|
|
for (const name of Object.keys(VueFunctions)) {
|
|
|
|
if (excludedVueHelpers.includes(name)) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
it(`should register ${name} globally`, () => {
|
2022-08-22 10:12:02 +00:00
|
|
|
expect(defaultPresets.find(a => a.from === 'vue')!.imports).toContain(name)
|
2021-11-05 14:39:14 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
})
|
2024-06-11 09:14:11 +00:00
|
|
|
|
|
|
|
describe('imports:nuxt/scripts', () => {
|
|
|
|
const scripts = scriptRegistry().map(s => s.import?.name).filter(Boolean)
|
|
|
|
const globalScripts = new Set([
|
|
|
|
'useScript',
|
|
|
|
'useAnalyticsPageEvent',
|
|
|
|
'useElementScriptTrigger',
|
|
|
|
'useConsentScriptTrigger',
|
2024-06-12 16:15:39 +00:00
|
|
|
// registered separately
|
|
|
|
'useScriptGoogleTagManager',
|
|
|
|
'useScriptGoogleAnalytics',
|
2024-06-11 09:14:11 +00:00
|
|
|
])
|
|
|
|
it.each(scriptsStubsPreset.imports)(`should register %s from @nuxt/scripts`, (name) => {
|
|
|
|
if (globalScripts.has(name)) { return }
|
|
|
|
|
|
|
|
expect(scripts).toContain(name)
|
|
|
|
})
|
|
|
|
it.each(scripts)(`should register %s from @nuxt/scripts`, (name) => {
|
|
|
|
expect(scriptsStubsPreset.imports).toContain(name)
|
|
|
|
})
|
|
|
|
})
|