Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, it } from 'vitest'
import { FixedTupleMap, MaybeWeakMap, TupleMap } from './cache'
import { FixedTupleMap, MaybeWeakMap, TupleMap } from '../cache'

describe('maybeWeakMap', () => {
it('should work', () => {
Expand Down
53 changes: 53 additions & 0 deletions packages/devtools-vite/src/app/utils/__tests__/color.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { beforeEach, describe, expect, it } from 'vitest'
import { isDark } from '../../composables/dark'
import { getHashColorFromString, getHsla, getPluginColor, predefinedColorMap } from '../color'

describe('getHashColorFromString', () => {
it('should get the same color with the same string', () => {
expect(getHashColorFromString('Vite')).toBe(getHashColorFromString('Vite'))
})
it('should get different colors with different strings', () => {
expect(getHashColorFromString('Vite')).not.toBe(getHashColorFromString('Devtools'))
})
})

describe('getHsla', () => {
beforeEach(() => {
isDark.value = false
})

it('light mode with default opacity', () => {
expect(getHsla(180)).toBe('hsla(180, 65%, 40%, 1)')
})

it('light mode with custom opacity', () => {
expect(getHsla(180, 0.5)).toBe('hsla(180, 65%, 40%, 0.5)')
})

it('dark mode with default opacity', () => {
isDark.value = true
expect(getHsla(180)).toBe('hsla(180, 50%, 60%, 1)')
})

it('dark mode with custom opacity', () => {
isDark.value = true
expect(getHsla(180, 0.8)).toBe('hsla(180, 50%, 60%, 0.8)')
})
})

describe('getPluginColor', () => {
it('should use predefinedColorMap with known name', () => {
for (const name in predefinedColorMap) {
if (Object.prototype.hasOwnProperty.call(predefinedColorMap, name)
&& name === name.replace(/[^a-z]+/gi, '').toLowerCase()) {
if (typeof predefinedColorMap[name] === 'number') {
expect(getPluginColor(`8080-=(🤔)${name}`)).toBe(getHsla(predefinedColorMap[name]))
}
}
}
})

it('should use getHashColorFromString with unknown name', () => {
expect(getPluginColor('😄Foo')).toBe(getHashColorFromString('foo'))
})
})
83 changes: 83 additions & 0 deletions packages/devtools-vite/src/app/utils/__tests__/filepath.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { describe, expect, it } from 'vitest'
import { getModuleNameFromPath, isBuiltInModule, isNodeModulePath, parseReadablePath } from '../filepath'

describe('isNodeModulePath', () => {
it('should return true if includes node_modules path', () => {
expect(isNodeModulePath('/foo/node_modules/bar')).toBeTruthy()
expect(isNodeModulePath('C:\\foo\\node_modules\\bar')).toBeTruthy()
})

it('should return true if package names', () => {
expect(isNodeModulePath('vite')).toBeTruthy()
expect(isNodeModulePath('@vitejs/devtools')).toBeTruthy()
expect(isNodeModulePath('#import')).toBeTruthy()
})

it('should return false if not node_modules', () => {
expect(isNodeModulePath('/foo/bar')).toBeFalsy()
})
})

describe('getModuleNameFromPath', () => {
it('should return package name', () => {
expect(getModuleNameFromPath('vite')).toBe('vite')
expect(getModuleNameFromPath('@vite/devtools')).toBe('@vite/devtools')
})

it('should return undefined with a non-module name', () => {
expect(getModuleNameFromPath('/foo/bar')).toBeUndefined()
expect(getModuleNameFromPath('C:\\foo\\bar')).toBeUndefined()
})

it('should return scope package name', () => {
expect(getModuleNameFromPath('/foo/bar/node_modules/@vitejs/devtools')).toBe('@vitejs/devtools')
expect(getModuleNameFromPath('C:\\foo\\node_modules\\@vitejs\\devtools')).toBe('@vitejs/devtools')
})

it('should return normal package name', () => {
expect(getModuleNameFromPath('/foo/bar/node_modules/vite')).toBe('vite')
expect(getModuleNameFromPath('C:\\foo\\node_modules\\@vitejs\\devtools')).toBe('@vitejs/devtools')
})
})

describe('isBuiltInModule', () => {
it('should return undefined with undefined name', () => {
expect(isBuiltInModule(undefined)).toBeUndefined()
})

it('should return true with a built-in module name', () => {
expect(isBuiltInModule('nuxt')).toBeTruthy()
})

it('should return false with a not built-in module name', () => {
expect(isBuiltInModule('foo')).toBeFalsy()
})
})

describe('parseReadablePath', () => {
it('should return path with package names', () => {
expect(parseReadablePath('vite', '/')).toEqual({ moduleName: 'vite', path: 'vite' })
expect(parseReadablePath('@vitejs/devtools', '/')).toEqual({ moduleName: '@vitejs/devtools', path: '@vitejs/devtools' })
expect(parseReadablePath('@vitejs\\devtools', '/')).toEqual({ moduleName: '@vitejs/devtools', path: '@vitejs/devtools' })
expect(parseReadablePath('@vitejs%2Fdevtools', '/')).toEqual({ moduleName: '@vitejs/devtools', path: '@vitejs/devtools' })
})

it('should return path with : unless Windows path', () => {
expect(parseReadablePath('nuxt:index.mjs', '/')).toEqual({ moduleName: 'nuxt:index.mjs', path: 'nuxt:index.mjs' })
})

it('should return moduleName and subpath', () => {
expect(parseReadablePath('/foo/node_modules/vite/dist/index.mjs', '/')).toEqual({ moduleName: 'vite', path: 'vite/dist/index.mjs' })
expect(parseReadablePath('C:\\foo\\node_modules\\vite\\dist\\index.mjs', 'C:\\')).toEqual({ moduleName: 'vite', path: 'vite/dist/index.mjs' })
})

it('should add ./ for no ./ items', () => {
expect(parseReadablePath('/foo/index.mjs', '/foo')).toEqual({ path: './index.mjs' })
expect(parseReadablePath('C:\\foo\\index.mjs', 'C:\\foo')).toEqual({ path: './index.mjs' })
})

it('should add replace ./.nuxt to #build for .nuxt items', () => {
expect(parseReadablePath('/foo/.nuxt/index.mjs', '/foo')).toEqual({ path: '#build/index.mjs' })
expect(parseReadablePath('C:\\foo\\.nuxt\\index.mjs', 'C:\\foo')).toEqual({ path: '#build/index.mjs' })
})
})
98 changes: 98 additions & 0 deletions packages/devtools-vite/src/app/utils/__tests__/format.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import type { ModuleDest, ModuleTreeNode } from '../../../shared/types/data'
import { describe, expect, it } from 'vitest'
import { bytesToHumanSize, getContentByteSize, toTree } from '../format'

describe('bytesToHumanSize', () => {
it('should return raw bytes (<1024)', () => {
expect(bytesToHumanSize(10)).toEqual([10, 'B'])
})

it('should return kb with proper digits', () => {
expect(bytesToHumanSize(1024)).toEqual(['1', 'KB'])
expect(bytesToHumanSize(1024 * 1.5)).toEqual(['1.5', 'KB'])
expect(bytesToHumanSize(1024 * 1.666, 1)).toEqual(['1.7', 'KB'])
})

it('should return mb with proper digits', () => {
expect(bytesToHumanSize(1024 * 1024)).toEqual(['1', 'MB'])
expect(bytesToHumanSize(1024 * 1024 * 1.5)).toEqual(['1.5', 'MB'])
expect(bytesToHumanSize(1024 * 1024 * 1.666, 1)).toEqual(['1.7', 'MB'])
})

// larger...
})

describe('getContentByteSize', () => {
it('should return 0 with empty string', () => {
expect(getContentByteSize('')).toBe(0)
})

it('should return bytes', () => {
expect(getContentByteSize('vite')).toBe(4)
})
})

describe('toTree', () => {
it('should work with empty modules', () => {
expect(toTree([], 'Root')).toEqual({
name: 'Root',
children: {},
items: [],
})
})

it('should work', () => {
const modules: ModuleDest[] = [
{
full: '/path/to/project/dist/src/components/Button.js',
path: 'src/components/Button.js',
},
{
full: '/path/to/project/dist/src/utils/helper.js',
path: 'src/utils/helper.js',
},
{
full: '/path/to/project/dist/index.js',
path: 'index.js',
},
]

expect(toTree(modules, 'Root')).toEqual({
name: 'Root',
children: {
src: {
name: 'src',
children: {
components: {
name: 'components',
children: {},
items: [
{
full: '/path/to/project/dist/src/components/Button.js',
path: 'src/components/Button.js',
},
],
},
utils: {
name: 'utils',
children: {},
items: [
{
full: '/path/to/project/dist/src/utils/helper.js',
path: 'src/utils/helper.js',
},
],
},
},
items: [],
},
},
items: [
{
full: '/path/to/project/dist/index.js',
path: 'index.js',
},
],
} satisfies ModuleTreeNode)
})
})
61 changes: 61 additions & 0 deletions packages/devtools-vite/src/app/utils/__tests__/icon.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { describe, expect, it } from 'vitest'
import { DefaultFileTypeRule, DefaultPluginType, getFileTypeFromModuleId, getFileTypeFromName, getPluginTypeFromName } from '../icon'

describe('getFileTypeFromName', () => {
it('should return correct rule by name', () => {
expect(getFileTypeFromName('vue').name).toBe('vue')
expect(getFileTypeFromName('ts').name).toBe('ts')
})

it('should return default rule for unknown names', () => {
expect(getFileTypeFromName('unknown')).toBe(DefaultFileTypeRule)
})
})

describe('getFileTypeFromModuleId', () => {
it('should match node_modules', () => {
expect(getFileTypeFromModuleId('/node_modules/vue/dist/vue.js').name).toBe('node_modules')
expect(getFileTypeFromModuleId('C:\\node_modules\\react\\index.js').name).toBe('node_modules')
})

it('should match virtual modules', () => {
expect(getFileTypeFromModuleId('virtual:my-module').name).toBe('virtual')
expect(getFileTypeFromModuleId('\0rollup-plugin').name).toBe('virtual')
})

it('should match file extensions', () => {
expect(getFileTypeFromModuleId('/src/App.vue').name).toBe('vue')
expect(getFileTypeFromModuleId('/src/index.ts').name).toBe('ts')
expect(getFileTypeFromModuleId('/src/index.tsx').name).toBe('jsx')
expect(getFileTypeFromModuleId('/src/index.js').name).toBe('js')
expect(getFileTypeFromModuleId('/src/style.css').name).toBe('css')
})

it('should handle query parameters', () => {
expect(getFileTypeFromModuleId('/src/App.vue?v=123').name).toBe('vue')
expect(getFileTypeFromModuleId('/src/App.vue?').name).toBe('vue')
})

it('should match packages', () => {
expect(getFileTypeFromModuleId('vite').name).toBe('package')
expect(getFileTypeFromModuleId('@vitejs/devtools').name).toBe('package')
})

it('should return default for unknown files', () => {
expect(getFileTypeFromModuleId('/unknown.xyz')).toBe(DefaultFileTypeRule)
})
})

describe('getPluginTypeFromName', () => {
it('should match plugin types', () => {
expect(getPluginTypeFromName('replace').name).toBe('rollup')
expect(getPluginTypeFromName('vite:css').name).toBe('vite')
expect(getPluginTypeFromName('unocss:core').name).toBe('unocss')
expect(getPluginTypeFromName('nuxt:pages').name).toBe('nuxt')
expect(getPluginTypeFromName('builtin:fs').name).toBe('builtin')
})

it('should return default for unknown plugins', () => {
expect(getPluginTypeFromName('custom-plugin')).toBe(DefaultPluginType)
})
})
24 changes: 24 additions & 0 deletions packages/devtools-vite/src/app/utils/__tests__/is.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { describe, expect, it } from 'vitest'
import { isNumeric } from '../is'

describe('isNumeric', () => {
it('should return true for numbers', () => {
expect(isNumeric(1)).toBeTruthy()
expect(isNumeric(0)).toBeTruthy()
expect(isNumeric(-1)).toBeTruthy()
})

it('should return false for non-numeric strings', () => {
expect(isNumeric('Vite')).toBeFalsy()
expect(isNumeric('123abc')).toBeFalsy()
})

it('should return true for numeric strings', () => {
expect(isNumeric('123')).toBeTruthy()
})

it('should return false for NaN/Infinity', () => {
expect(isNumeric(Number.NaN)).toBeTruthy()
expect(isNumeric(Infinity)).toBeTruthy()
})
})
2 changes: 1 addition & 1 deletion packages/devtools-vite/src/app/utils/color.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function getHsla(
* - 240: blue
* - 270: purple
*/
const predefinedColorMap = {
export const predefinedColorMap = {
error: 0,
client: 60,
bailout: -1,
Expand Down
Loading