@agions/taroviz 1.1.0 → 1.2.0
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.
- package/README.md +318 -53
- package/dist/index.esm.js +67955 -3318
- package/package.json +102 -20
- package/src/__tests__/integration.test.tsx +168 -0
- package/src/adapters/__tests__/index.test.ts +91 -0
- package/src/adapters/h5/__tests__/index.test.ts +156 -0
- package/src/adapters/h5/index.ts +301 -0
- package/src/adapters/harmony/index.ts +274 -0
- package/src/adapters/index.ts +234 -0
- package/src/adapters/swan/index.ts +274 -0
- package/src/adapters/tt/index.ts +274 -0
- package/src/adapters/types.ts +162 -0
- package/src/adapters/weapp/index.ts +237 -0
- package/src/charts/bar/__tests__/index.test.tsx +113 -0
- package/src/charts/bar/index.tsx +27 -0
- package/src/charts/common/BaseChartWrapper.tsx +136 -0
- package/src/charts/funnel/index.tsx +33 -0
- package/src/charts/gauge/index.tsx +33 -0
- package/src/charts/heatmap/index.tsx +33 -0
- package/src/charts/index.ts +21 -0
- package/src/charts/line/__tests__/index.test.tsx +107 -0
- package/src/charts/line/index.tsx +27 -0
- package/src/charts/pie/__tests__/index.test.tsx +112 -0
- package/src/charts/pie/index.tsx +22 -0
- package/src/charts/radar/index.tsx +33 -0
- package/src/charts/scatter/index.tsx +33 -0
- package/src/charts/types.ts +146 -0
- package/src/charts/utils.ts +56 -0
- package/src/core/__tests__/platform.test.ts +48 -0
- package/src/core/animation/AnimationManager.ts +391 -0
- package/src/core/animation/index.ts +20 -0
- package/src/core/animation/types.ts +248 -0
- package/src/core/components/BaseChart.tsx +1319 -0
- package/src/core/index.ts +19 -0
- package/src/core/types/chart.ts +66 -0
- package/src/core/types/common.ts +224 -0
- package/src/core/types/index.ts +281 -0
- package/src/core/types/platform.ts +325 -0
- package/src/core/utils/__tests__/common.test.ts +52 -0
- package/src/core/utils/__tests__/environment.test.ts +94 -0
- package/src/core/utils/__tests__/i18n.test.ts +247 -0
- package/src/core/utils/__tests__/index.test.ts +219 -0
- package/src/core/utils/__tests__/uuid.test.ts +78 -0
- package/src/core/utils/chartInstances.ts +69 -0
- package/src/core/utils/codeGenerator/CodeGenerator.ts +655 -0
- package/src/core/utils/codeGenerator/index.ts +13 -0
- package/src/core/utils/codeGenerator/types.ts +200 -0
- package/src/core/utils/common.ts +58 -0
- package/src/core/utils/configGenerator/ConfigGenerator.ts +583 -0
- package/src/core/utils/configGenerator/index.ts +13 -0
- package/src/core/utils/configGenerator/types.ts +445 -0
- package/src/core/utils/debug/DebugPanel.tsx +637 -0
- package/src/core/utils/debug/debugger.ts +322 -0
- package/src/core/utils/debug/index.ts +21 -0
- package/src/core/utils/debug/types.ts +142 -0
- package/src/core/utils/i18n.ts +452 -0
- package/src/core/utils/index.ts +162 -0
- package/src/core/utils/performance/PerformanceAnalyzer.ts +586 -0
- package/src/core/utils/performance/index.ts +13 -0
- package/src/core/utils/performance/types.ts +180 -0
- package/src/core/utils/uuid.ts +30 -0
- package/src/editor/ThemeEditor.tsx +449 -0
- package/src/editor/index.ts +10 -0
- package/src/hooks/__tests__/index.test.tsx +333 -0
- package/src/hooks/index.ts +214 -0
- package/src/index.ts +75 -0
- package/src/main.tsx +247 -0
- package/src/react-dom.d.ts +7 -0
- package/src/themes/__tests__/index.test.ts +91 -0
- package/src/themes/index.ts +465 -0
- package/dist/index.esm.js.map +0 -1
- package/dist/index.js +0 -4012
- package/dist/index.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,36 +1,118 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agions/taroviz",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "基于 Taro 和 ECharts 的多端图表组件库",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
|
-
"sideEffects": false,
|
|
9
8
|
"files": [
|
|
10
9
|
"dist",
|
|
11
|
-
"
|
|
10
|
+
"src",
|
|
11
|
+
"README.md",
|
|
12
|
+
"LICENSE"
|
|
12
13
|
],
|
|
13
14
|
"scripts": {
|
|
14
|
-
"dev": "webpack --mode
|
|
15
|
-
"build": "
|
|
16
|
-
"clean": "rimraf dist"
|
|
15
|
+
"dev": "webpack serve --mode development",
|
|
16
|
+
"build": "webpack --mode production",
|
|
17
|
+
"clean": "rimraf dist",
|
|
18
|
+
"test": "jest",
|
|
19
|
+
"cypress:open": "cypress open",
|
|
20
|
+
"cypress:run": "cypress run",
|
|
21
|
+
"cypress:component": "cypress open --component",
|
|
22
|
+
"test:e2e": "cypress run --e2e",
|
|
23
|
+
"lint": "eslint src --ext .ts,.tsx",
|
|
24
|
+
"type-check": "tsc --noEmit",
|
|
25
|
+
"prepare": "husky install",
|
|
26
|
+
"docs:api": "node scripts/update-docs.js generate",
|
|
27
|
+
"docs:html": "node scripts/update-docs.js html",
|
|
28
|
+
"docs:build": "node scripts/update-docs.js all",
|
|
29
|
+
"docs:serve": "node scripts/update-docs.js serve",
|
|
30
|
+
"docs:update": "node scripts/update-docs.js",
|
|
31
|
+
"docs:fix": "node scripts/doc-fix.js",
|
|
32
|
+
"deps:update": "node scripts/update-deps.js"
|
|
17
33
|
},
|
|
18
|
-
"
|
|
19
|
-
"
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@babel/plugin-proposal-decorators": "^7.25.9",
|
|
36
|
+
"@babel/plugin-transform-runtime": "^7.28.5",
|
|
37
|
+
"@babel/preset-env": "^7.26.9",
|
|
38
|
+
"@babel/preset-react": "^7.26.3",
|
|
39
|
+
"@babel/preset-typescript": "^7.27.0",
|
|
40
|
+
"@testing-library/cypress": "^10.1.0",
|
|
41
|
+
"@testing-library/dom": "^10.4.1",
|
|
42
|
+
"@testing-library/jest-dom": "^6.9.1",
|
|
43
|
+
"@testing-library/react": "^16.3.0",
|
|
44
|
+
"@types/jest": "^29.5.12",
|
|
45
|
+
"@types/node": "^20.11.24",
|
|
46
|
+
"@types/react": "^18.2.61",
|
|
47
|
+
"@types/react-dom": "^18.3.7",
|
|
48
|
+
"@types/testing-library__jest-dom": "^5.14.9",
|
|
49
|
+
"@typescript-eslint/eslint-plugin": "^7.1.0",
|
|
50
|
+
"@typescript-eslint/parser": "^7.1.0",
|
|
51
|
+
"babel-loader": "^10.0.0",
|
|
52
|
+
"clean-webpack-plugin": "^4.0.0",
|
|
53
|
+
"core-js": "3.41.0",
|
|
54
|
+
"css-loader": "^7.1.2",
|
|
55
|
+
"cypress": "^15.7.0",
|
|
56
|
+
"eslint": "^8.57.0",
|
|
57
|
+
"eslint-config-prettier": "^9.1.0",
|
|
58
|
+
"eslint-import-resolver-typescript": "^4.3.2",
|
|
59
|
+
"eslint-plugin-import": "^2.31.0",
|
|
60
|
+
"eslint-plugin-prettier": "^5.1.3",
|
|
61
|
+
"eslint-plugin-react": "^7.33.2",
|
|
62
|
+
"eslint-plugin-react-hooks": "^4.6.0",
|
|
63
|
+
"fork-ts-checker-webpack-plugin": "^9.1.0",
|
|
64
|
+
"glob": "^10.3.10",
|
|
65
|
+
"husky": "^9.0.11",
|
|
66
|
+
"jest": "^29.7.0",
|
|
67
|
+
"jest-environment-jsdom": "^30.2.0",
|
|
68
|
+
"lint-staged": "^15.2.2",
|
|
69
|
+
"marked": "^12.0.2",
|
|
70
|
+
"mini-css-extract-plugin": "^2.9.2",
|
|
71
|
+
"prettier": "^3.2.5",
|
|
72
|
+
"react-dom": "^18.3.1",
|
|
73
|
+
"rimraf": "^5.0.5",
|
|
74
|
+
"sass": "^1.86.3",
|
|
75
|
+
"sass-loader": "^16.0.5",
|
|
76
|
+
"terser-webpack-plugin": "^5.3.14",
|
|
77
|
+
"ts-jest": "^29.1.2",
|
|
78
|
+
"ts-loader": "^9.5.2",
|
|
79
|
+
"typedoc": "^0.28.2",
|
|
80
|
+
"typedoc-plugin-markdown": "^3.17.1",
|
|
81
|
+
"typescript": "^5.3.3",
|
|
82
|
+
"webpack": "^5.90.3",
|
|
83
|
+
"webpack-bundle-analyzer": "^4.10.2",
|
|
84
|
+
"webpack-cli": "^5.1.4",
|
|
85
|
+
"webpack-dev-server": "^5.0.4",
|
|
86
|
+
"whatwg-fetch": "^3.6.20"
|
|
20
87
|
},
|
|
21
88
|
"dependencies": {
|
|
22
|
-
"@
|
|
23
|
-
"
|
|
24
|
-
"
|
|
25
|
-
"@agions/taroviz-data": "1.1.0",
|
|
26
|
-
"@agions/taroviz-hooks": "1.1.0",
|
|
27
|
-
"@agions/taroviz-themes": "1.1.0"
|
|
89
|
+
"@babel/runtime": "^7.28.4",
|
|
90
|
+
"echarts": "^5.4.3",
|
|
91
|
+
"react": "^18.2.0"
|
|
28
92
|
},
|
|
29
93
|
"peerDependencies": {
|
|
30
|
-
"@tarojs/components": "
|
|
31
|
-
"@tarojs/
|
|
32
|
-
"
|
|
33
|
-
"react": ">=16.13.0"
|
|
94
|
+
"@tarojs/components": "^3.6.0",
|
|
95
|
+
"@tarojs/runtime": "^3.6.0",
|
|
96
|
+
"@tarojs/taro": "^3.6.0"
|
|
34
97
|
},
|
|
35
|
-
"
|
|
98
|
+
"engines": {
|
|
99
|
+
"node": ">=16.0.0"
|
|
100
|
+
},
|
|
101
|
+
"keywords": [
|
|
102
|
+
"taro",
|
|
103
|
+
"echarts",
|
|
104
|
+
"chart",
|
|
105
|
+
"component",
|
|
106
|
+
"multi-platform"
|
|
107
|
+
],
|
|
108
|
+
"author": "TaroViz Team",
|
|
109
|
+
"license": "MIT",
|
|
110
|
+
"repository": {
|
|
111
|
+
"type": "git",
|
|
112
|
+
"url": "https://github.com/agions/taroviz.git"
|
|
113
|
+
},
|
|
114
|
+
"homepage": "https://agions.github.io/taroviz/",
|
|
115
|
+
"bugs": {
|
|
116
|
+
"url": "https://github.com/agions/taroviz/issues"
|
|
117
|
+
}
|
|
36
118
|
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { render } from '@testing-library/react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
|
|
4
|
+
import { LineChart } from '../charts';
|
|
5
|
+
|
|
6
|
+
// Mock ECharts and adapters
|
|
7
|
+
jest.mock('echarts/core', () => ({
|
|
8
|
+
use: jest.fn(),
|
|
9
|
+
init: jest.fn(() => ({
|
|
10
|
+
setOption: jest.fn(),
|
|
11
|
+
showLoading: jest.fn(),
|
|
12
|
+
hideLoading: jest.fn(),
|
|
13
|
+
on: jest.fn(),
|
|
14
|
+
off: jest.fn(),
|
|
15
|
+
dispose: jest.fn(),
|
|
16
|
+
resize: jest.fn(),
|
|
17
|
+
})),
|
|
18
|
+
getInstanceByDom: jest.fn(),
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
// Mock specific ECharts chart imports
|
|
22
|
+
jest.mock('echarts/charts', () => ({
|
|
23
|
+
LineChart: jest.fn(),
|
|
24
|
+
BarChart: jest.fn(),
|
|
25
|
+
PieChart: jest.fn(),
|
|
26
|
+
}));
|
|
27
|
+
|
|
28
|
+
jest.mock('echarts/components', () => ({
|
|
29
|
+
GridComponent: jest.fn(),
|
|
30
|
+
TooltipComponent: jest.fn(),
|
|
31
|
+
TitleComponent: jest.fn(),
|
|
32
|
+
LegendComponent: jest.fn(),
|
|
33
|
+
}));
|
|
34
|
+
|
|
35
|
+
jest.mock('../adapters', () => ({
|
|
36
|
+
getAdapter: jest.fn(() => ({
|
|
37
|
+
init: jest.fn(),
|
|
38
|
+
setOption: jest.fn(),
|
|
39
|
+
resize: jest.fn(),
|
|
40
|
+
dispose: jest.fn(),
|
|
41
|
+
on: jest.fn(),
|
|
42
|
+
off: jest.fn(),
|
|
43
|
+
showLoading: jest.fn(),
|
|
44
|
+
hideLoading: jest.fn(),
|
|
45
|
+
})),
|
|
46
|
+
}));
|
|
47
|
+
|
|
48
|
+
jest.mock('../charts/common/BaseChartWrapper', () => ({
|
|
49
|
+
__esModule: true,
|
|
50
|
+
default: (props: any) => (
|
|
51
|
+
<div
|
|
52
|
+
data-testid="base-chart-wrapper"
|
|
53
|
+
className={`taroviz-${props.chartType}`}
|
|
54
|
+
style={{ width: props.width, height: props.height }}
|
|
55
|
+
>
|
|
56
|
+
<div data-testid="chart-option">{JSON.stringify(props.option)}</div>
|
|
57
|
+
<div data-testid="chart-loading">{props.loading ? 'loading' : 'not-loading'}</div>
|
|
58
|
+
</div>
|
|
59
|
+
),
|
|
60
|
+
}));
|
|
61
|
+
|
|
62
|
+
describe('Integration Tests', () => {
|
|
63
|
+
describe('Chart Rendering Flow', () => {
|
|
64
|
+
it('should render a complete chart with all components', () => {
|
|
65
|
+
const mockOption = {
|
|
66
|
+
xAxis: { type: 'category' as const, data: ['Mon', 'Tue', 'Wed'] },
|
|
67
|
+
yAxis: { type: 'value' as const },
|
|
68
|
+
series: [{ data: [120, 200, 150], type: 'line' as const }],
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const { getByTestId } = render(
|
|
72
|
+
<LineChart option={mockOption} width="500px" height="300px" loading={false} />
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const chartWrapper = getByTestId('base-chart-wrapper');
|
|
76
|
+
const chartOption = getByTestId('chart-option');
|
|
77
|
+
const chartLoading = getByTestId('chart-loading');
|
|
78
|
+
|
|
79
|
+
expect(chartWrapper).toBeInTheDocument();
|
|
80
|
+
expect(chartWrapper).toHaveClass('taroviz-line-chart');
|
|
81
|
+
expect(chartOption).toHaveTextContent(JSON.stringify(mockOption));
|
|
82
|
+
expect(chartLoading).toHaveTextContent('not-loading');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('should handle chart option updates', () => {
|
|
86
|
+
const initialOption = {
|
|
87
|
+
xAxis: { type: 'category' as const, data: ['Mon', 'Tue', 'Wed'] },
|
|
88
|
+
yAxis: { type: 'value' as const },
|
|
89
|
+
series: [{ data: [120, 200, 150], type: 'line' as const }],
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const updatedOption = {
|
|
93
|
+
xAxis: { type: 'category' as const, data: ['Mon', 'Tue', 'Wed', 'Thu'] },
|
|
94
|
+
yAxis: { type: 'value' as const },
|
|
95
|
+
series: [{ data: [120, 200, 150, 250], type: 'line' as const }],
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const { getByTestId, rerender } = render(
|
|
99
|
+
<LineChart option={initialOption} width="500px" height="300px" />
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
// Check initial rendering
|
|
103
|
+
let chartOption = getByTestId('chart-option');
|
|
104
|
+
expect(chartOption).toHaveTextContent(JSON.stringify(initialOption));
|
|
105
|
+
|
|
106
|
+
// Update option and check
|
|
107
|
+
rerender(<LineChart option={updatedOption} width="500px" height="300px" />);
|
|
108
|
+
|
|
109
|
+
chartOption = getByTestId('chart-option');
|
|
110
|
+
expect(chartOption).toHaveTextContent(JSON.stringify(updatedOption));
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('should handle loading state changes', () => {
|
|
114
|
+
const mockOption = {
|
|
115
|
+
xAxis: { type: 'category' as const, data: ['Mon', 'Tue', 'Wed'] },
|
|
116
|
+
yAxis: { type: 'value' as const },
|
|
117
|
+
series: [{ data: [120, 200, 150], type: 'line' as const }],
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
const { getByTestId, rerender } = render(<LineChart option={mockOption} loading={false} />);
|
|
121
|
+
|
|
122
|
+
// Check initial loading state
|
|
123
|
+
let chartLoading = getByTestId('chart-loading');
|
|
124
|
+
expect(chartLoading).toHaveTextContent('not-loading');
|
|
125
|
+
|
|
126
|
+
// Update loading state and check
|
|
127
|
+
rerender(<LineChart option={mockOption} loading={true} />);
|
|
128
|
+
|
|
129
|
+
chartLoading = getByTestId('chart-loading');
|
|
130
|
+
expect(chartLoading).toHaveTextContent('loading');
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('should render different chart types with consistent API', () => {
|
|
134
|
+
// Test LineChart
|
|
135
|
+
const lineOption = {
|
|
136
|
+
xAxis: { type: 'category' as const, data: ['Mon', 'Tue', 'Wed'] },
|
|
137
|
+
yAxis: { type: 'value' as const },
|
|
138
|
+
series: [{ data: [120, 200, 150], type: 'line' as const }],
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const { getByTestId: getLineChart } = render(
|
|
142
|
+
<LineChart option={lineOption} width="400px" height="200px" />
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
const lineChartWrapper = getLineChart('base-chart-wrapper');
|
|
146
|
+
expect(lineChartWrapper).toBeInTheDocument();
|
|
147
|
+
expect(lineChartWrapper).toHaveClass('taroviz-line-chart');
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
describe('Chart Event Handling', () => {
|
|
152
|
+
it('should pass events to chart instance', () => {
|
|
153
|
+
const mockOption = {
|
|
154
|
+
xAxis: { type: 'category' as const, data: ['Mon', 'Tue', 'Wed'] },
|
|
155
|
+
yAxis: { type: 'value' as const },
|
|
156
|
+
series: [{ data: [120, 200, 150], type: 'line' as const }],
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
const mockOnClick = jest.fn();
|
|
160
|
+
|
|
161
|
+
render(<LineChart option={mockOption} onEvents={{ click: mockOnClick }} />);
|
|
162
|
+
|
|
163
|
+
// The event should be passed to the chart instance via BaseChartWrapper
|
|
164
|
+
// We can verify this by checking that the BaseChartWrapper received the onEvents prop
|
|
165
|
+
// In our mock, this is handled by the getAdapter mock
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
});
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { PlatformType } from '../../core';
|
|
2
|
+
import { detectPlatform, getEnv, getAdapter } from '../index';
|
|
3
|
+
|
|
4
|
+
// Mock dependencies
|
|
5
|
+
jest.mock('../h5', () => ({
|
|
6
|
+
default: {
|
|
7
|
+
create: jest.fn(() => ({
|
|
8
|
+
init: jest.fn(),
|
|
9
|
+
setOption: jest.fn(),
|
|
10
|
+
resize: jest.fn(),
|
|
11
|
+
dispose: jest.fn(),
|
|
12
|
+
})),
|
|
13
|
+
},
|
|
14
|
+
}));
|
|
15
|
+
|
|
16
|
+
jest.mock('../weapp', () => ({
|
|
17
|
+
default: {
|
|
18
|
+
create: jest.fn(() => ({
|
|
19
|
+
init: jest.fn(),
|
|
20
|
+
setOption: jest.fn(),
|
|
21
|
+
resize: jest.fn(),
|
|
22
|
+
dispose: jest.fn(),
|
|
23
|
+
})),
|
|
24
|
+
},
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
describe('Adapter Functions', () => {
|
|
28
|
+
describe('getEnv', () => {
|
|
29
|
+
it('should return h5 for browser environment', () => {
|
|
30
|
+
const env = getEnv();
|
|
31
|
+
expect(env).toBe('h5');
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
describe('getAdapter', () => {
|
|
36
|
+
it('should return adapter instance for browser environment', () => {
|
|
37
|
+
const adapter = getAdapter({});
|
|
38
|
+
expect(adapter).toBeDefined();
|
|
39
|
+
expect(typeof adapter.init).toBe('function');
|
|
40
|
+
expect(typeof adapter.setOption).toBe('function');
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('should return adapter instance with custom options', () => {
|
|
44
|
+
const mockOptions = {
|
|
45
|
+
width: 500,
|
|
46
|
+
height: 300,
|
|
47
|
+
theme: 'dark',
|
|
48
|
+
renderer: 'canvas' as const,
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const adapter = getAdapter(mockOptions);
|
|
52
|
+
expect(adapter).toBeDefined();
|
|
53
|
+
expect(typeof adapter.init).toBe('function');
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe('detectPlatform', () => {
|
|
58
|
+
it('should return H5 by default', () => {
|
|
59
|
+
const platform = detectPlatform();
|
|
60
|
+
expect(platform).toBe(PlatformType.H5);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
describe('Cross-Platform Compatibility', () => {
|
|
65
|
+
it('should have consistent interface across all platforms', () => {
|
|
66
|
+
const adapter = getAdapter({});
|
|
67
|
+
|
|
68
|
+
// 确保所有平台的适配器都有相同的方法接口
|
|
69
|
+
const requiredMethods = ['init', 'setOption', 'resize', 'dispose'];
|
|
70
|
+
|
|
71
|
+
requiredMethods.forEach(method => {
|
|
72
|
+
expect(typeof adapter[method as keyof typeof adapter]).toBe('function');
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
it('should handle different option types across platforms', () => {
|
|
77
|
+
// 测试不同类型的选项
|
|
78
|
+
const testOptions = [
|
|
79
|
+
{ width: 500, height: 300 },
|
|
80
|
+
{ theme: 'dark' },
|
|
81
|
+
{ renderer: 'canvas' as const },
|
|
82
|
+
{ renderer: 'svg' as const },
|
|
83
|
+
];
|
|
84
|
+
|
|
85
|
+
testOptions.forEach(options => {
|
|
86
|
+
const adapter = getAdapter(options);
|
|
87
|
+
expect(adapter).toBeDefined();
|
|
88
|
+
});
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
});
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import * as echarts from 'echarts/core';
|
|
2
|
+
|
|
3
|
+
import H5Adapter from '../index';
|
|
4
|
+
|
|
5
|
+
// Mock ECharts renderers first
|
|
6
|
+
jest.mock('echarts/renderers', () => ({
|
|
7
|
+
CanvasRenderer: jest.fn(),
|
|
8
|
+
SVGRenderer: jest.fn(),
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
// Mock ECharts components
|
|
12
|
+
jest.mock('echarts/components', () => ({
|
|
13
|
+
GridComponent: jest.fn(),
|
|
14
|
+
TooltipComponent: jest.fn(),
|
|
15
|
+
TitleComponent: jest.fn(),
|
|
16
|
+
LegendComponent: jest.fn(),
|
|
17
|
+
}));
|
|
18
|
+
|
|
19
|
+
// Mock ECharts charts
|
|
20
|
+
jest.mock('echarts/charts', () => ({
|
|
21
|
+
LineChart: jest.fn(),
|
|
22
|
+
BarChart: jest.fn(),
|
|
23
|
+
PieChart: jest.fn(),
|
|
24
|
+
}));
|
|
25
|
+
|
|
26
|
+
// Mock ECharts
|
|
27
|
+
jest.mock('echarts/core', () => ({
|
|
28
|
+
init: jest.fn(() => ({
|
|
29
|
+
setOption: jest.fn(),
|
|
30
|
+
resize: jest.fn(),
|
|
31
|
+
on: jest.fn(),
|
|
32
|
+
off: jest.fn(),
|
|
33
|
+
showLoading: jest.fn(),
|
|
34
|
+
hideLoading: jest.fn(),
|
|
35
|
+
dispose: jest.fn(),
|
|
36
|
+
getDataURL: jest.fn(() => 'data:image/png;base64,test'),
|
|
37
|
+
clear: jest.fn(),
|
|
38
|
+
})),
|
|
39
|
+
use: jest.fn(),
|
|
40
|
+
}));
|
|
41
|
+
|
|
42
|
+
describe('H5Adapter', () => {
|
|
43
|
+
let adapter: H5Adapter;
|
|
44
|
+
let mockContainer: HTMLElement;
|
|
45
|
+
|
|
46
|
+
beforeEach(() => {
|
|
47
|
+
// Create a mock container
|
|
48
|
+
mockContainer = document.createElement('div');
|
|
49
|
+
mockContainer.id = 'test-canvas';
|
|
50
|
+
document.body.appendChild(mockContainer);
|
|
51
|
+
|
|
52
|
+
// Create adapter instance
|
|
53
|
+
adapter = H5Adapter.create({
|
|
54
|
+
canvasId: 'test-canvas',
|
|
55
|
+
width: 500,
|
|
56
|
+
height: 300,
|
|
57
|
+
theme: 'dark',
|
|
58
|
+
renderer: 'canvas',
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
afterEach(() => {
|
|
63
|
+
// Clean up
|
|
64
|
+
document.body.removeChild(mockContainer);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('initialization', () => {
|
|
68
|
+
it('should create an instance with correct options', () => {
|
|
69
|
+
expect(adapter).toBeInstanceOf(H5Adapter);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('should initialize the chart instance', () => {
|
|
73
|
+
const instance = adapter.init();
|
|
74
|
+
expect(instance).toBeDefined();
|
|
75
|
+
expect(echarts.init).toHaveBeenCalled();
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
describe('chart operations', () => {
|
|
80
|
+
it('should set chart options', () => {
|
|
81
|
+
const mockOption = {
|
|
82
|
+
xAxis: { type: 'category' as const, data: ['Mon', 'Tue'] },
|
|
83
|
+
yAxis: { type: 'value' as const },
|
|
84
|
+
series: [{ data: [120, 200], type: 'line' as const }],
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
adapter.setOption(mockOption);
|
|
88
|
+
|
|
89
|
+
// After initialization, setOption should be called on the instance
|
|
90
|
+
const _instance = adapter.init();
|
|
91
|
+
adapter.setOption(mockOption);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it('should handle theme setting', () => {
|
|
95
|
+
adapter.setTheme('light');
|
|
96
|
+
expect(adapter['options'].theme).toBe('light');
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should resize the chart', () => {
|
|
100
|
+
const _instance = adapter.init();
|
|
101
|
+
adapter.resize();
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('should show and hide loading', () => {
|
|
105
|
+
const _instance = adapter.init();
|
|
106
|
+
adapter.showLoading();
|
|
107
|
+
adapter.hideLoading();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should convert chart to data URL', () => {
|
|
111
|
+
const _instance = adapter.init();
|
|
112
|
+
const dataUrl = adapter.convertToDataURL();
|
|
113
|
+
expect(dataUrl).toBeDefined();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it('should clear the chart', () => {
|
|
117
|
+
const _instance = adapter.init();
|
|
118
|
+
adapter.clear();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('should dispose the chart', () => {
|
|
122
|
+
const _instance = adapter.init();
|
|
123
|
+
adapter.dispose();
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe('event handling', () => {
|
|
128
|
+
it('should bind and unbind events', () => {
|
|
129
|
+
const _instance = adapter.init();
|
|
130
|
+
const mockHandler = jest.fn();
|
|
131
|
+
|
|
132
|
+
adapter.on('click', mockHandler);
|
|
133
|
+
adapter.off('click', mockHandler);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
describe('adapter information', () => {
|
|
138
|
+
it('should return adapter name', () => {
|
|
139
|
+
expect(adapter.getName()).toBe('H5Adapter');
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
it('should return adapter version', () => {
|
|
143
|
+
expect(adapter.getVersion()).toBe('1.1.1');
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
it('should return platform info', () => {
|
|
147
|
+
const platformInfo = adapter.getPlatformInfo();
|
|
148
|
+
expect(platformInfo).toEqual(
|
|
149
|
+
expect.objectContaining({
|
|
150
|
+
platform: 'h5',
|
|
151
|
+
renderer: 'canvas',
|
|
152
|
+
})
|
|
153
|
+
);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
});
|