Skip to content

Commit d0885a2

Browse files
authored
test: add tests for utils in devtools-vite (#77)
1 parent b9c2e07 commit d0885a2

7 files changed

Lines changed: 321 additions & 2 deletions

File tree

packages/devtools-vite/src/app/utils/cache.test.ts renamed to packages/devtools-vite/src/app/utils/__tests__/cache.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { describe, expect, it } from 'vitest'
2-
import { FixedTupleMap, MaybeWeakMap, TupleMap } from './cache'
2+
import { FixedTupleMap, MaybeWeakMap, TupleMap } from '../cache'
33

44
describe('maybeWeakMap', () => {
55
it('should work', () => {
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { beforeEach, describe, expect, it } from 'vitest'
2+
import { isDark } from '../../composables/dark'
3+
import { getHashColorFromString, getHsla, getPluginColor, predefinedColorMap } from '../color'
4+
5+
describe('getHashColorFromString', () => {
6+
it('should get the same color with the same string', () => {
7+
expect(getHashColorFromString('Vite')).toBe(getHashColorFromString('Vite'))
8+
})
9+
it('should get different colors with different strings', () => {
10+
expect(getHashColorFromString('Vite')).not.toBe(getHashColorFromString('Devtools'))
11+
})
12+
})
13+
14+
describe('getHsla', () => {
15+
beforeEach(() => {
16+
isDark.value = false
17+
})
18+
19+
it('light mode with default opacity', () => {
20+
expect(getHsla(180)).toBe('hsla(180, 65%, 40%, 1)')
21+
})
22+
23+
it('light mode with custom opacity', () => {
24+
expect(getHsla(180, 0.5)).toBe('hsla(180, 65%, 40%, 0.5)')
25+
})
26+
27+
it('dark mode with default opacity', () => {
28+
isDark.value = true
29+
expect(getHsla(180)).toBe('hsla(180, 50%, 60%, 1)')
30+
})
31+
32+
it('dark mode with custom opacity', () => {
33+
isDark.value = true
34+
expect(getHsla(180, 0.8)).toBe('hsla(180, 50%, 60%, 0.8)')
35+
})
36+
})
37+
38+
describe('getPluginColor', () => {
39+
it('should use predefinedColorMap with known name', () => {
40+
for (const name in predefinedColorMap) {
41+
if (Object.prototype.hasOwnProperty.call(predefinedColorMap, name)
42+
&& name === name.replace(/[^a-z]+/gi, '').toLowerCase()) {
43+
if (typeof predefinedColorMap[name] === 'number') {
44+
expect(getPluginColor(`8080-=(🤔)${name}`)).toBe(getHsla(predefinedColorMap[name]))
45+
}
46+
}
47+
}
48+
})
49+
50+
it('should use getHashColorFromString with unknown name', () => {
51+
expect(getPluginColor('😄Foo')).toBe(getHashColorFromString('foo'))
52+
})
53+
})
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { getModuleNameFromPath, isBuiltInModule, isNodeModulePath, parseReadablePath } from '../filepath'
3+
4+
describe('isNodeModulePath', () => {
5+
it('should return true if includes node_modules path', () => {
6+
expect(isNodeModulePath('/foo/node_modules/bar')).toBeTruthy()
7+
expect(isNodeModulePath('C:\\foo\\node_modules\\bar')).toBeTruthy()
8+
})
9+
10+
it('should return true if package names', () => {
11+
expect(isNodeModulePath('vite')).toBeTruthy()
12+
expect(isNodeModulePath('@vitejs/devtools')).toBeTruthy()
13+
expect(isNodeModulePath('#import')).toBeTruthy()
14+
})
15+
16+
it('should return false if not node_modules', () => {
17+
expect(isNodeModulePath('/foo/bar')).toBeFalsy()
18+
})
19+
})
20+
21+
describe('getModuleNameFromPath', () => {
22+
it('should return package name', () => {
23+
expect(getModuleNameFromPath('vite')).toBe('vite')
24+
expect(getModuleNameFromPath('@vite/devtools')).toBe('@vite/devtools')
25+
})
26+
27+
it('should return undefined with a non-module name', () => {
28+
expect(getModuleNameFromPath('/foo/bar')).toBeUndefined()
29+
expect(getModuleNameFromPath('C:\\foo\\bar')).toBeUndefined()
30+
})
31+
32+
it('should return scope package name', () => {
33+
expect(getModuleNameFromPath('/foo/bar/node_modules/@vitejs/devtools')).toBe('@vitejs/devtools')
34+
expect(getModuleNameFromPath('C:\\foo\\node_modules\\@vitejs\\devtools')).toBe('@vitejs/devtools')
35+
})
36+
37+
it('should return normal package name', () => {
38+
expect(getModuleNameFromPath('/foo/bar/node_modules/vite')).toBe('vite')
39+
expect(getModuleNameFromPath('C:\\foo\\node_modules\\@vitejs\\devtools')).toBe('@vitejs/devtools')
40+
})
41+
})
42+
43+
describe('isBuiltInModule', () => {
44+
it('should return undefined with undefined name', () => {
45+
expect(isBuiltInModule(undefined)).toBeUndefined()
46+
})
47+
48+
it('should return true with a built-in module name', () => {
49+
expect(isBuiltInModule('nuxt')).toBeTruthy()
50+
})
51+
52+
it('should return false with a not built-in module name', () => {
53+
expect(isBuiltInModule('foo')).toBeFalsy()
54+
})
55+
})
56+
57+
describe('parseReadablePath', () => {
58+
it('should return path with package names', () => {
59+
expect(parseReadablePath('vite', '/')).toEqual({ moduleName: 'vite', path: 'vite' })
60+
expect(parseReadablePath('@vitejs/devtools', '/')).toEqual({ moduleName: '@vitejs/devtools', path: '@vitejs/devtools' })
61+
expect(parseReadablePath('@vitejs\\devtools', '/')).toEqual({ moduleName: '@vitejs/devtools', path: '@vitejs/devtools' })
62+
expect(parseReadablePath('@vitejs%2Fdevtools', '/')).toEqual({ moduleName: '@vitejs/devtools', path: '@vitejs/devtools' })
63+
})
64+
65+
it('should return path with : unless Windows path', () => {
66+
expect(parseReadablePath('nuxt:index.mjs', '/')).toEqual({ moduleName: 'nuxt:index.mjs', path: 'nuxt:index.mjs' })
67+
})
68+
69+
it('should return moduleName and subpath', () => {
70+
expect(parseReadablePath('/foo/node_modules/vite/dist/index.mjs', '/')).toEqual({ moduleName: 'vite', path: 'vite/dist/index.mjs' })
71+
expect(parseReadablePath('C:\\foo\\node_modules\\vite\\dist\\index.mjs', 'C:\\')).toEqual({ moduleName: 'vite', path: 'vite/dist/index.mjs' })
72+
})
73+
74+
it('should add ./ for no ./ items', () => {
75+
expect(parseReadablePath('/foo/index.mjs', '/foo')).toEqual({ path: './index.mjs' })
76+
expect(parseReadablePath('C:\\foo\\index.mjs', 'C:\\foo')).toEqual({ path: './index.mjs' })
77+
})
78+
79+
it('should add replace ./.nuxt to #build for .nuxt items', () => {
80+
expect(parseReadablePath('/foo/.nuxt/index.mjs', '/foo')).toEqual({ path: '#build/index.mjs' })
81+
expect(parseReadablePath('C:\\foo\\.nuxt\\index.mjs', 'C:\\foo')).toEqual({ path: '#build/index.mjs' })
82+
})
83+
})
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import type { ModuleDest, ModuleTreeNode } from '../../../shared/types/data'
2+
import { describe, expect, it } from 'vitest'
3+
import { bytesToHumanSize, getContentByteSize, toTree } from '../format'
4+
5+
describe('bytesToHumanSize', () => {
6+
it('should return raw bytes (<1024)', () => {
7+
expect(bytesToHumanSize(10)).toEqual([10, 'B'])
8+
})
9+
10+
it('should return kb with proper digits', () => {
11+
expect(bytesToHumanSize(1024)).toEqual(['1', 'KB'])
12+
expect(bytesToHumanSize(1024 * 1.5)).toEqual(['1.5', 'KB'])
13+
expect(bytesToHumanSize(1024 * 1.666, 1)).toEqual(['1.7', 'KB'])
14+
})
15+
16+
it('should return mb with proper digits', () => {
17+
expect(bytesToHumanSize(1024 * 1024)).toEqual(['1', 'MB'])
18+
expect(bytesToHumanSize(1024 * 1024 * 1.5)).toEqual(['1.5', 'MB'])
19+
expect(bytesToHumanSize(1024 * 1024 * 1.666, 1)).toEqual(['1.7', 'MB'])
20+
})
21+
22+
// larger...
23+
})
24+
25+
describe('getContentByteSize', () => {
26+
it('should return 0 with empty string', () => {
27+
expect(getContentByteSize('')).toBe(0)
28+
})
29+
30+
it('should return bytes', () => {
31+
expect(getContentByteSize('vite')).toBe(4)
32+
})
33+
})
34+
35+
describe('toTree', () => {
36+
it('should work with empty modules', () => {
37+
expect(toTree([], 'Root')).toEqual({
38+
name: 'Root',
39+
children: {},
40+
items: [],
41+
})
42+
})
43+
44+
it('should work', () => {
45+
const modules: ModuleDest[] = [
46+
{
47+
full: '/path/to/project/dist/src/components/Button.js',
48+
path: 'src/components/Button.js',
49+
},
50+
{
51+
full: '/path/to/project/dist/src/utils/helper.js',
52+
path: 'src/utils/helper.js',
53+
},
54+
{
55+
full: '/path/to/project/dist/index.js',
56+
path: 'index.js',
57+
},
58+
]
59+
60+
expect(toTree(modules, 'Root')).toEqual({
61+
name: 'Root',
62+
children: {
63+
src: {
64+
name: 'src',
65+
children: {
66+
components: {
67+
name: 'components',
68+
children: {},
69+
items: [
70+
{
71+
full: '/path/to/project/dist/src/components/Button.js',
72+
path: 'src/components/Button.js',
73+
},
74+
],
75+
},
76+
utils: {
77+
name: 'utils',
78+
children: {},
79+
items: [
80+
{
81+
full: '/path/to/project/dist/src/utils/helper.js',
82+
path: 'src/utils/helper.js',
83+
},
84+
],
85+
},
86+
},
87+
items: [],
88+
},
89+
},
90+
items: [
91+
{
92+
full: '/path/to/project/dist/index.js',
93+
path: 'index.js',
94+
},
95+
],
96+
} satisfies ModuleTreeNode)
97+
})
98+
})
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { DefaultFileTypeRule, DefaultPluginType, getFileTypeFromModuleId, getFileTypeFromName, getPluginTypeFromName } from '../icon'
3+
4+
describe('getFileTypeFromName', () => {
5+
it('should return correct rule by name', () => {
6+
expect(getFileTypeFromName('vue').name).toBe('vue')
7+
expect(getFileTypeFromName('ts').name).toBe('ts')
8+
})
9+
10+
it('should return default rule for unknown names', () => {
11+
expect(getFileTypeFromName('unknown')).toBe(DefaultFileTypeRule)
12+
})
13+
})
14+
15+
describe('getFileTypeFromModuleId', () => {
16+
it('should match node_modules', () => {
17+
expect(getFileTypeFromModuleId('/node_modules/vue/dist/vue.js').name).toBe('node_modules')
18+
expect(getFileTypeFromModuleId('C:\\node_modules\\react\\index.js').name).toBe('node_modules')
19+
})
20+
21+
it('should match virtual modules', () => {
22+
expect(getFileTypeFromModuleId('virtual:my-module').name).toBe('virtual')
23+
expect(getFileTypeFromModuleId('\0rollup-plugin').name).toBe('virtual')
24+
})
25+
26+
it('should match file extensions', () => {
27+
expect(getFileTypeFromModuleId('/src/App.vue').name).toBe('vue')
28+
expect(getFileTypeFromModuleId('/src/index.ts').name).toBe('ts')
29+
expect(getFileTypeFromModuleId('/src/index.tsx').name).toBe('jsx')
30+
expect(getFileTypeFromModuleId('/src/index.js').name).toBe('js')
31+
expect(getFileTypeFromModuleId('/src/style.css').name).toBe('css')
32+
})
33+
34+
it('should handle query parameters', () => {
35+
expect(getFileTypeFromModuleId('/src/App.vue?v=123').name).toBe('vue')
36+
expect(getFileTypeFromModuleId('/src/App.vue?').name).toBe('vue')
37+
})
38+
39+
it('should match packages', () => {
40+
expect(getFileTypeFromModuleId('vite').name).toBe('package')
41+
expect(getFileTypeFromModuleId('@vitejs/devtools').name).toBe('package')
42+
})
43+
44+
it('should return default for unknown files', () => {
45+
expect(getFileTypeFromModuleId('/unknown.xyz')).toBe(DefaultFileTypeRule)
46+
})
47+
})
48+
49+
describe('getPluginTypeFromName', () => {
50+
it('should match plugin types', () => {
51+
expect(getPluginTypeFromName('replace').name).toBe('rollup')
52+
expect(getPluginTypeFromName('vite:css').name).toBe('vite')
53+
expect(getPluginTypeFromName('unocss:core').name).toBe('unocss')
54+
expect(getPluginTypeFromName('nuxt:pages').name).toBe('nuxt')
55+
expect(getPluginTypeFromName('builtin:fs').name).toBe('builtin')
56+
})
57+
58+
it('should return default for unknown plugins', () => {
59+
expect(getPluginTypeFromName('custom-plugin')).toBe(DefaultPluginType)
60+
})
61+
})
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { describe, expect, it } from 'vitest'
2+
import { isNumeric } from '../is'
3+
4+
describe('isNumeric', () => {
5+
it('should return true for numbers', () => {
6+
expect(isNumeric(1)).toBeTruthy()
7+
expect(isNumeric(0)).toBeTruthy()
8+
expect(isNumeric(-1)).toBeTruthy()
9+
})
10+
11+
it('should return false for non-numeric strings', () => {
12+
expect(isNumeric('Vite')).toBeFalsy()
13+
expect(isNumeric('123abc')).toBeFalsy()
14+
})
15+
16+
it('should return true for numeric strings', () => {
17+
expect(isNumeric('123')).toBeTruthy()
18+
})
19+
20+
it('should return false for NaN/Infinity', () => {
21+
expect(isNumeric(Number.NaN)).toBeTruthy()
22+
expect(isNumeric(Infinity)).toBeTruthy()
23+
})
24+
})

packages/devtools-vite/src/app/utils/color.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export function getHsla(
3535
* - 240: blue
3636
* - 270: purple
3737
*/
38-
const predefinedColorMap = {
38+
export const predefinedColorMap = {
3939
error: 0,
4040
client: 60,
4141
bailout: -1,

0 commit comments

Comments
 (0)