@be-link/smart-test 1.0.1-beta.6 → 1.0.1-beta.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test-generator.d.ts","sourceRoot":"","sources":["../../src/analyzer/test-generator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"test-generator.d.ts","sourceRoot":"","sources":["../../src/analyzer/test-generator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAK9C;;;;GAIG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAC,CAAS;IAExB;;OAEG;IACG,oBAAoB,CAAC,QAAQ,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAwB3F;;OAEG;IACH,OAAO,CAAC,aAAa;IAiBrB;;OAEG;YACW,cAAc;IAiD5B;;OAEG;IACH,OAAO,CAAC,aAAa;IAkHrB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IA8DzB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAK5B;;OAEG;IACH,OAAO,CAAC,eAAe;CASxB"}
|
package/dist/cli/index.js
CHANGED
|
@@ -1675,10 +1675,13 @@ class TestGenerator {
|
|
|
1675
1675
|
*/
|
|
1676
1676
|
async generateFromAnalysis(analysis, mockFileName) {
|
|
1677
1677
|
const config = await configLoader.load();
|
|
1678
|
+
// 获取 baseURL 和页面路径
|
|
1679
|
+
const baseURL = config.playwright?.baseURL || 'http://localhost:8080';
|
|
1680
|
+
const pagePath = this.inferPagePath(analysis.filePath);
|
|
1678
1681
|
// 尝试使用 AI 生成
|
|
1679
1682
|
if (config.ai?.apiKey) {
|
|
1680
1683
|
try {
|
|
1681
|
-
const aiTest = await this.generateWithAI(analysis, mockFileName, config);
|
|
1684
|
+
const aiTest = await this.generateWithAI(analysis, mockFileName, config, baseURL, pagePath);
|
|
1682
1685
|
if (aiTest) {
|
|
1683
1686
|
return aiTest;
|
|
1684
1687
|
}
|
|
@@ -1689,17 +1692,33 @@ class TestGenerator {
|
|
|
1689
1692
|
}
|
|
1690
1693
|
}
|
|
1691
1694
|
// 降级到基础模板
|
|
1692
|
-
return this.generateBasicTest(analysis, mockFileName);
|
|
1695
|
+
return this.generateBasicTest(analysis, mockFileName, baseURL, pagePath);
|
|
1696
|
+
}
|
|
1697
|
+
/**
|
|
1698
|
+
* 从文件路径推断页面路由
|
|
1699
|
+
*/
|
|
1700
|
+
inferPagePath(filePath) {
|
|
1701
|
+
// 提取文件名(不含扩展名)
|
|
1702
|
+
const fileName = filePath
|
|
1703
|
+
.split('/')
|
|
1704
|
+
.pop()
|
|
1705
|
+
?.replace(/\.(tsx?|jsx?)$/, '') || 'page';
|
|
1706
|
+
// 将 PascalCase 或 camelCase 转换为 kebab-case
|
|
1707
|
+
const kebabCase = fileName
|
|
1708
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
1709
|
+
.replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
|
|
1710
|
+
.toLowerCase();
|
|
1711
|
+
return `/${kebabCase}`;
|
|
1693
1712
|
}
|
|
1694
1713
|
/**
|
|
1695
1714
|
* 使用 AI 生成测试代码
|
|
1696
1715
|
*/
|
|
1697
|
-
async generateWithAI(analysis, mockFileName, config) {
|
|
1716
|
+
async generateWithAI(analysis, mockFileName, config, baseURL, pagePath) {
|
|
1698
1717
|
this.openai = new OpenAI({
|
|
1699
1718
|
apiKey: config.ai.apiKey,
|
|
1700
1719
|
baseURL: config.ai.baseURL,
|
|
1701
1720
|
});
|
|
1702
|
-
const prompt = this.buildAIPrompt(analysis, mockFileName);
|
|
1721
|
+
const prompt = this.buildAIPrompt(analysis, mockFileName, baseURL, pagePath);
|
|
1703
1722
|
try {
|
|
1704
1723
|
const response = await this.openai.chat.completions.create({
|
|
1705
1724
|
model: config.ai.model || 'qwen-plus',
|
|
@@ -1713,7 +1732,8 @@ class TestGenerator {
|
|
|
1713
1732
|
1. 所有注释必须使用中文
|
|
1714
1733
|
2. 测试描述使用中文
|
|
1715
1734
|
3. 只输出代码,不要任何解释
|
|
1716
|
-
4. 包含 AI 视觉检查测试用例(使用 aiReviewScreenshot
|
|
1735
|
+
4. 包含 AI 视觉检查测试用例(使用 aiReviewScreenshot)
|
|
1736
|
+
5. page.goto() 必须使用完整的 URL(包含 baseURL)`,
|
|
1717
1737
|
},
|
|
1718
1738
|
{
|
|
1719
1739
|
role: 'user',
|
|
@@ -1735,8 +1755,9 @@ class TestGenerator {
|
|
|
1735
1755
|
/**
|
|
1736
1756
|
* 构建 AI 生成测试的 prompt
|
|
1737
1757
|
*/
|
|
1738
|
-
buildAIPrompt(analysis, mockFileName) {
|
|
1758
|
+
buildAIPrompt(analysis, mockFileName, baseURL, pagePath) {
|
|
1739
1759
|
const { components, apiTypes, filePath } = analysis;
|
|
1760
|
+
const fullURL = `${baseURL}${pagePath}`;
|
|
1740
1761
|
// 构建组件信息描述
|
|
1741
1762
|
let componentInfo = '';
|
|
1742
1763
|
if (components && components.length > 0) {
|
|
@@ -1779,6 +1800,11 @@ ${propsStr}`;
|
|
|
1779
1800
|
## 源文件
|
|
1780
1801
|
${filePath}
|
|
1781
1802
|
|
|
1803
|
+
## 页面 URL
|
|
1804
|
+
- Base URL: ${baseURL}
|
|
1805
|
+
- 页面路径: ${pagePath}
|
|
1806
|
+
- 完整 URL: ${fullURL}
|
|
1807
|
+
|
|
1782
1808
|
## 组件信息
|
|
1783
1809
|
${componentInfo || '无组件'}
|
|
1784
1810
|
|
|
@@ -1800,6 +1826,7 @@ ${mockFileName}
|
|
|
1800
1826
|
6. test.describe 和 test 描述使用中文
|
|
1801
1827
|
7. 合理使用 beforeEach 设置 mock 数据
|
|
1802
1828
|
8. 处理 AI 检查未配置的情况
|
|
1829
|
+
9. **重要**: page.goto() 必须使用完整 URL: '${fullURL}'
|
|
1803
1830
|
|
|
1804
1831
|
## 输出格式
|
|
1805
1832
|
只输出 TypeScript 代码,格式如下:
|
|
@@ -1816,14 +1843,18 @@ test.describe('组件名称 页面测试', () => {
|
|
|
1816
1843
|
});
|
|
1817
1844
|
|
|
1818
1845
|
test('应该成功加载页面', async ({ page }) => {
|
|
1846
|
+
// 访问页面(使用完整 URL)
|
|
1847
|
+
await page.goto('${fullURL}');
|
|
1819
1848
|
// 测试代码
|
|
1820
1849
|
});
|
|
1821
1850
|
|
|
1822
1851
|
test('用户交互测试', async ({ page }) => {
|
|
1852
|
+
await page.goto('${fullURL}');
|
|
1823
1853
|
// 测试代码
|
|
1824
1854
|
});
|
|
1825
1855
|
|
|
1826
1856
|
test('AI 视觉检查 - 页面内容验证', async ({ page }) => {
|
|
1857
|
+
await page.goto('${fullURL}');
|
|
1827
1858
|
// AI 视觉检查代码
|
|
1828
1859
|
});
|
|
1829
1860
|
});
|
|
@@ -1833,9 +1864,10 @@ test.describe('组件名称 页面测试', () => {
|
|
|
1833
1864
|
/**
|
|
1834
1865
|
* 生成基础测试模板
|
|
1835
1866
|
*/
|
|
1836
|
-
generateBasicTest(analysis, mockFileName) {
|
|
1867
|
+
generateBasicTest(analysis, mockFileName, baseURL, pagePath) {
|
|
1837
1868
|
const { components, filePath } = analysis;
|
|
1838
1869
|
const componentName = components?.[0]?.name || this.extractComponentName(filePath);
|
|
1870
|
+
const fullURL = `${baseURL}${pagePath}`;
|
|
1839
1871
|
return `import { test, expect } from '@playwright/test';
|
|
1840
1872
|
import { aiReviewScreenshot } from '@be-link/smart-test';
|
|
1841
1873
|
import { mockApis } from './${mockFileName}';
|
|
@@ -1848,7 +1880,7 @@ test.describe('${componentName} 页面测试', () => {
|
|
|
1848
1880
|
|
|
1849
1881
|
test('应该成功加载页面', async ({ page }) => {
|
|
1850
1882
|
// 访问页面
|
|
1851
|
-
await page.goto('
|
|
1883
|
+
await page.goto('${fullURL}');
|
|
1852
1884
|
|
|
1853
1885
|
// 等待页面加载
|
|
1854
1886
|
await page.waitForLoadState('networkidle');
|
|
@@ -1859,7 +1891,7 @@ test.describe('${componentName} 页面测试', () => {
|
|
|
1859
1891
|
|
|
1860
1892
|
test('页面应该正确渲染内容', async ({ page }) => {
|
|
1861
1893
|
// 访问页面
|
|
1862
|
-
await page.goto('
|
|
1894
|
+
await page.goto('${fullURL}');
|
|
1863
1895
|
|
|
1864
1896
|
// 等待页面加载
|
|
1865
1897
|
await page.waitForLoadState('networkidle');
|
|
@@ -1870,7 +1902,7 @@ test.describe('${componentName} 页面测试', () => {
|
|
|
1870
1902
|
|
|
1871
1903
|
test('AI 视觉检查 - 页面内容验证', async ({ page }) => {
|
|
1872
1904
|
// 访问页面
|
|
1873
|
-
await page.goto('
|
|
1905
|
+
await page.goto('${fullURL}');
|
|
1874
1906
|
|
|
1875
1907
|
// 等待页面加载
|
|
1876
1908
|
await page.waitForLoadState('networkidle');
|
package/dist/index.esm.js
CHANGED
|
@@ -144,6 +144,7 @@ async function aiReviewScreenshot(page, options) {
|
|
|
144
144
|
// 解析 AI 响应
|
|
145
145
|
const content = completion?.choices[0]?.message?.content || '';
|
|
146
146
|
const result = parseAiResponse(content);
|
|
147
|
+
console.log('[smart-test] AI 检查结果:', result);
|
|
147
148
|
return { ...result, rawResponse: content };
|
|
148
149
|
}
|
|
149
150
|
catch (error) {
|
package/dist/index.js
CHANGED
|
@@ -146,6 +146,7 @@ async function aiReviewScreenshot(page, options) {
|
|
|
146
146
|
// 解析 AI 响应
|
|
147
147
|
const content = completion?.choices[0]?.message?.content || '';
|
|
148
148
|
const result = parseAiResponse(content);
|
|
149
|
+
console.log('[smart-test] AI 检查结果:', result);
|
|
149
150
|
return { ...result, rawResponse: content };
|
|
150
151
|
}
|
|
151
152
|
catch (error) {
|
package/package.json
CHANGED