"添加前端模板和运行代码模块"
This commit is contained in:
211
qiming-vite-plugin-design-mode/test/utils/babelHelpers.test.ts
Normal file
211
qiming-vite-plugin-design-mode/test/utils/babelHelpers.test.ts
Normal file
@@ -0,0 +1,211 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import {
|
||||
isReactComponentName,
|
||||
getJSXElementBaseName,
|
||||
isStringLiteralAttribute,
|
||||
extractStringAttributeValue,
|
||||
createSourcePositionString,
|
||||
parseSourcePositionString,
|
||||
} from '../../packages/plugin/src/utils/babelHelpers';
|
||||
import * as t from '@babel/types';
|
||||
|
||||
describe('babelHelpers', () => {
|
||||
describe('isReactComponentName', () => {
|
||||
it('应该识别大写开头的组件名', () => {
|
||||
expect(isReactComponentName('App')).toBe(true);
|
||||
expect(isReactComponentName('Button')).toBe(true);
|
||||
expect(isReactComponentName('MyComponent')).toBe(true);
|
||||
});
|
||||
|
||||
it('应该识别小写开头的非组件名', () => {
|
||||
expect(isReactComponentName('app')).toBe(false);
|
||||
expect(isReactComponentName('button')).toBe(false);
|
||||
expect(isReactComponentName('myComponent')).toBe(false);
|
||||
});
|
||||
|
||||
it('应该处理特殊字符', () => {
|
||||
expect(isReactComponentName('_App')).toBe(false);
|
||||
expect(isReactComponentName('$Component')).toBe(false);
|
||||
expect(isReactComponentName('123Component')).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getJSXElementBaseName', () => {
|
||||
it('应该从JSXIdentifier获取名称', () => {
|
||||
const identifier = t.jSXIdentifier('div');
|
||||
const name = getJSXElementBaseName(identifier);
|
||||
expect(name).toBe('div');
|
||||
});
|
||||
|
||||
it('应该从JSXMemberExpression获取属性名', () => {
|
||||
const memberExpr = t.jSXMemberExpression(
|
||||
t.jSXIdentifier('React'),
|
||||
t.jSXIdentifier('Component')
|
||||
);
|
||||
const name = getJSXElementBaseName(memberExpr);
|
||||
expect(name).toBe('Component');
|
||||
});
|
||||
|
||||
it('应该处理未知类型', () => {
|
||||
const unknown = t.stringLiteral('test');
|
||||
const name = getJSXElementBaseName(unknown as any);
|
||||
expect(name).toBe('unknown');
|
||||
});
|
||||
});
|
||||
|
||||
describe('isStringLiteralAttribute', () => {
|
||||
it('应该识别字符串字面量属性', () => {
|
||||
const attr = t.jSXAttribute(
|
||||
t.jSXIdentifier('className'),
|
||||
t.stringLiteral('test')
|
||||
);
|
||||
|
||||
const result = isStringLiteralAttribute(attr, 'className');
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('应该识别非字符串字面量属性', () => {
|
||||
const attr = t.jSXAttribute(
|
||||
t.jSXIdentifier('className'),
|
||||
t.jSXExpressionContainer(t.identifier('classNameVar'))
|
||||
);
|
||||
|
||||
const result = isStringLiteralAttribute(attr, 'className');
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
|
||||
it('应该识别属性名不匹配的情况', () => {
|
||||
const attr = t.jSXAttribute(
|
||||
t.jSXIdentifier('id'),
|
||||
t.stringLiteral('test')
|
||||
);
|
||||
|
||||
const result = isStringLiteralAttribute(attr, 'className');
|
||||
expect(result).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('extractStringAttributeValue', () => {
|
||||
it('应该提取字符串属性值', () => {
|
||||
const openingElement = t.jSXOpeningElement(
|
||||
t.jSXIdentifier('div'),
|
||||
[
|
||||
t.jSXAttribute(
|
||||
t.jSXIdentifier('className'),
|
||||
t.stringLiteral('container')
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
const value = extractStringAttributeValue(openingElement, 'className');
|
||||
expect(value).toBe('container');
|
||||
});
|
||||
|
||||
it('应该返回null当属性不存在时', () => {
|
||||
const openingElement = t.jSXOpeningElement(
|
||||
t.jSXIdentifier('div'),
|
||||
[]
|
||||
);
|
||||
|
||||
const value = extractStringAttributeValue(openingElement, 'className');
|
||||
expect(value).toBeNull();
|
||||
});
|
||||
|
||||
it('应该返回null当属性不是字符串字面量时', () => {
|
||||
const openingElement = t.jSXOpeningElement(
|
||||
t.jSXIdentifier('div'),
|
||||
[
|
||||
t.jSXAttribute(
|
||||
t.jSXIdentifier('className'),
|
||||
t.jSXExpressionContainer(t.identifier('classNameVar'))
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
const value = extractStringAttributeValue(openingElement, 'className');
|
||||
expect(value).toBeNull();
|
||||
});
|
||||
|
||||
it('应该提取id属性值', () => {
|
||||
const openingElement = t.jSXOpeningElement(
|
||||
t.jSXIdentifier('div'),
|
||||
[
|
||||
t.jSXAttribute(
|
||||
t.jSXIdentifier('id'),
|
||||
t.stringLiteral('app')
|
||||
),
|
||||
]
|
||||
);
|
||||
|
||||
const value = extractStringAttributeValue(openingElement, 'id');
|
||||
expect(value).toBe('app');
|
||||
});
|
||||
});
|
||||
|
||||
describe('createSourcePositionString', () => {
|
||||
it('应该创建正确的位置字符串', () => {
|
||||
const position = createSourcePositionString('src/App.tsx', 10, 5);
|
||||
expect(position).toBe('src/App.tsx:10:5');
|
||||
});
|
||||
|
||||
it('应该处理不同的文件名', () => {
|
||||
const position = createSourcePositionString('components/Button.tsx', 20, 15);
|
||||
expect(position).toBe('components/Button.tsx:20:15');
|
||||
});
|
||||
|
||||
it('应该处理行号和列号为0的情况', () => {
|
||||
const position = createSourcePositionString('test.tsx', 0, 0);
|
||||
expect(position).toBe('test.tsx:0:0');
|
||||
});
|
||||
});
|
||||
|
||||
describe('parseSourcePositionString', () => {
|
||||
it('应该解析正确的位置字符串', () => {
|
||||
const result = parseSourcePositionString('src/App.tsx:10:5');
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result?.fileName).toBe('src/App.tsx');
|
||||
expect(result?.lineNumber).toBe(10);
|
||||
expect(result?.columnNumber).toBe(5);
|
||||
});
|
||||
|
||||
it('应该处理不同的文件名', () => {
|
||||
const result = parseSourcePositionString('components/Button.tsx:20:15');
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result?.fileName).toBe('components/Button.tsx');
|
||||
expect(result?.lineNumber).toBe(20);
|
||||
expect(result?.columnNumber).toBe(15);
|
||||
});
|
||||
|
||||
it('应该返回null当格式不正确时', () => {
|
||||
expect(parseSourcePositionString('invalid')).toBeNull();
|
||||
expect(parseSourcePositionString('src/App.tsx:10')).toBeNull();
|
||||
expect(parseSourcePositionString('src/App.tsx:10:5:extra')).toBeNull();
|
||||
});
|
||||
|
||||
it('应该返回null当行号或列号不是数字时', () => {
|
||||
expect(parseSourcePositionString('src/App.tsx:abc:5')).toBeNull();
|
||||
expect(parseSourcePositionString('src/App.tsx:10:def')).toBeNull();
|
||||
expect(parseSourcePositionString('src/App.tsx:abc:def')).toBeNull();
|
||||
});
|
||||
|
||||
it('应该处理行号和列号为0的情况', () => {
|
||||
const result = parseSourcePositionString('test.tsx:0:0');
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result?.lineNumber).toBe(0);
|
||||
expect(result?.columnNumber).toBe(0);
|
||||
});
|
||||
|
||||
it('应该处理负数行号或列号', () => {
|
||||
// 虽然负数在实际情况中不应该出现,但函数应该能处理
|
||||
const result = parseSourcePositionString('test.tsx:-1:-1');
|
||||
|
||||
expect(result).not.toBeNull();
|
||||
expect(result?.lineNumber).toBe(-1);
|
||||
expect(result?.columnNumber).toBe(-1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user