blob: 4172c3245c873c9f61d7772479725321956815b4 [file]
<!DOCTYPE html>
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1" />
<script src="lib/simpleRequire.js"></script>
<script src="lib/config.js"></script>
<script src="lib/jquery.min.js"></script>
<script src="lib/facePrint.js"></script>
<script src="lib/testHelper.js"></script>
<script src="lib/draggable.js"></script>
<!-- <script src="ut/lib/canteen.js"></script> -->
<link rel="stylesheet" href="lib/reset.css" />
</head>
<body>
<style>
</style>
<div id="main_layout"></div>
<div id="main_edge_cases"></div>
<div id="main_self_layout"></div>
<div id="main_dim_data_edge_cases"></div>
<script>
require([
'echarts',
], function (echarts) {
const MatrixClampOption = {
none: 0,
all: 1,
body: 2,
corner: 3,
};
var LEVEL_SIZE_1 = 15;
var LEVEL_SIZE_2 = 20;
var LEVEL_SIZE_3 = '10%';
var LEVEL_SIZE_4 = '0%';
var CELL_SIZE_1 = 30;
var CELL_SIZE_2 = 0;
var BODY_COMMON_COLOR = 'rgba(200, 150, 20, 0.1)';
var BODY_R2_A2_COLOR = 'rgba(200, 155, 0)';
var BODY_R1_B2_COLOR = 'rgba(200, 115, 200, 0.3)';
var X_COMMON_COLOR = 'rgba(22, 188, 212, 0.1)';
var X_T1_COLOR = 'rgba(12,122,250,0.8)';
var bodyData = [
{
coord: ['R2', 'A3'],
mergeCells: true,
},
{
coord: [['R1', 'S'], 'A'],
itemStyle: {
color: 'rgb(220,240,130)',
}
},
{
coord: ['R1', ['B4', 'C']],
mergeCells: true,
},
{
coord: [['R1', 'R2'], ['B2', 'B3']],
itemStyle: {
borderWidth: 4,
borderColor: 'orange',
color: 'red',
},
mergeCells: true,
},
{
coord: ['R2', 'A2'],
itemStyle: {
borderWidth: 4,
borderColor: 'blue',
color: BODY_R2_A2_COLOR,
},
z2: 200,
},
{
coord: [['R2', 'T'], 'B2'], // Overlap span, should be ignored.
mergeCells: true,
itemStyle: {
borderWidth: 4,
borderColor: 'rgb(200, 152, 222)',
color: BODY_R1_B2_COLOR,
},
_desc: 'expand to cover all merged cells'
},
{
coord: ['T', ['A1', 'A31']], // Overlap span, should be ignored.
mergeCells: true,
itemStyle: {
borderColor: 'rgb(123,134,10)',
borderWidth: 3,
color: 'rgb(220,230,170)',
},
z2: 200,
},
{
coord: ['R2', 'E'],
value: 'very long long long text',
label: {
color: 'red',
}
},
{
coord: ['U', null],
coordClamp: true,
itemStyle: {
color: 'rgb(220,230,170)',
},
},
{
coord: [NaN, 'F'],
coordClamp: true,
mergeCells: true,
}
];
var cornerData = [
{
coord: [null, -2],
coordClamp: true,
value: 'some',
mergeCells: true,
}
]
const MATRIX_BACKGROUND_STYLE_MAP = {
do_nothing: {
backgroundStyle: {},
x: {
itemStyle: {},
},
},
style1: {
backgroundStyle: {
borderWidth: 5,
},
x: {
itemStyle: {
borderWidth: 2,
color: 'red',
borderColor: 'rgba(11,222,33)'
}
}
},
style2: {
backgroundStyle: {
borderWidth: 1,
},
x: {
itemStyle: {
borderWidth: 1,
color: 'none',
borderColor: 'blue'
}
}
},
};
// --- state ------
let _xShowing = true;
let _yShowing = true;
let _convertFromPixelClampOpt = undefined;
let _convertToPointCaseItem = null;
let _matrixBgStyleIndex = 0;
let _textOverflow = 'truncate'; // internal default value.
// ----------------
var option;
option = {
backgroundColor: '#eee',
tooltip: {},
title: {
text: '',
right: 'center',
},
matrix: {
left: 120,
right: '29%',
tooltip: {
show: true,
formatter(params) {
return params.name;
}
},
x: {
label: {
},
itemStyle: {
color: X_COMMON_COLOR
},
levels: [null, {levelSize: LEVEL_SIZE_1}],
data: [
{
value: 'R',
children: ['R1', {value: 'R2', size: CELL_SIZE_1}]
},
{
value: 'S'
},
{
value: 'T',
children: [
{
value: 'T1',
itemStyle: {
borderWidth: 3,
borderColor: 'rgba(12,12,190)',
color: X_T1_COLOR,
},
label: {
fontSize: 22,
color: '#fff',
textBorderColor: '#333',
textBorderWidth: 2,
},
children: ['T11']
}
]
},
{
value: 'long long header text 1',
label: {
color: 'rgb(211,111,0)',
},
children: [{
value: 'long long header text 2',
label: {
color: 'rgb(211,81,0)',
}
}]
},
{
value: 'U',
size: 20,
},
{
value: 'V',
size: 20,
}
]
},
y: {
levelSize: LEVEL_SIZE_2,
levels: [
null,
{levelSize: LEVEL_SIZE_4},
null,
null,
{levelSize: LEVEL_SIZE_3}
],
data: [{
value: 'LLL',
children: [{
value: 'LL',
children: [
{
value: 'A',
children: ['A1', 'A2', {
value: 'A3',
children: ['A31', 'A32']
}]
}, {
value: 'B',
children: ['B1', 'B2', 'B3', 'B4']
}, {
value: 'C',
}, {
value: 'D',
size: CELL_SIZE_2,
}
]
}, {
value: 'E',
}, {
value: 'F',
itemStyle: {
color: '#bbb'
}
}]
}]
},
body: {
data: bodyData,
label: {
},
itemStyle: {
color: BODY_COMMON_COLOR
}
},
corner: {
itemStyle: {
borderWidth: 1,
},
data: cornerData,
}
},
graphic: {
elements: [{
right: 5,
y: 5,
id: 'info_bodyData',
type: 'text',
style: {
text: 'Check body cell merge and style:\n' + testHelper.printObject(bodyData, {lineBreakMaxColumn: 40}),
fontSize: 7,
}
}, {
left: 5,
y: 5,
id: 'info_cornerData',
type: 'text',
style: {
text: 'Check corner cell merge and style:\n' + testHelper.printObject(cornerData, {lineBreakMaxColumn: 40}),
fontSize: 7,
}
}, {
x: 120,
y: 5,
id: 'info2',
type: 'text',
style: {
text: [
'Check background: ',
` BODY_COMMON_COLOR = ${BODY_COMMON_COLOR}`,
` BODY_R2_A2_COLOR = ${BODY_R2_A2_COLOR}`,
` BODY_R1_B2_COLOR = ${BODY_R1_B2_COLOR}`,
` X_COMMON_COLOR = ${X_COMMON_COLOR}`,
` X_T1_COLOR = ${X_T1_COLOR}`,
].join('\n'),
fontSize: 7,
}
}]
},
grid: [{
id: 'aa',
coordinateSystem: 'matrix',
coord: ['R2', 'B3'],
top: 5,
left: 5,
right: 5,
bottom: 5,
containLabel: true,
}, {
id: 'bb',
coordinateSystem: 'matrix',
coord: ['R1', 'B4'],
top: 5,
left: 5,
right: 5,
bottom: 5,
containLabel: true,
}],
xAxis: [{
id: 'aa',
gridId: 'aa',
axisLabel: {fontSize: 9}
}, {
id: 'bb',
gridId: 'bb',
data: ['bb1', 'bb2', 'bb3'],
axisLabel: {fontSize: 9}
}],
yAxis: [{
id: 'aa',
gridId: 'aa',
interval: Infinity,
axisLabel: {fontSize: 9, showMinLabel: true, showMaxLabel: true,},
}, {
id: 'bb',
gridId: 'bb',
interval: Infinity,
axisLabel: {fontSize: 9, showMinLabel: true, showMaxLabel: true,},
}],
series: [{
type: 'scatter',
coordinateSystem: 'matrix',
symbolSize: 30,
data: [
['R1', 'A1', 10], ['R2', 'A1', 20], ['R1', 'A2', 30]
],
label: {
show: true,
formatter: params => {
return params.data[2];
}
}
}, {
// type: 'effectScatter',
type: 'scatter',
coordinateSystem: 'matrix',
symbolSize: function (val) {
return val[2] / 3;
},
data: [
['R2', 'A2', 40], ['R1', 'A31', 50], ['R2', 'A3', 60]
],
}, {
type: 'scatter',
name: 'right desc',
silent: true,
coordinateSystem: 'matrix',
symbolSize: 0,
symbolOffset: [0, 10],
label: {show: true, overflow: 'break', minMargin: 15},
labelLine: {show: true},
labelLayout: {
x: '73%',
moveOverlap: 'shiftY',
width: 70,
},
encode: {label: [0, 1, 2]},
data: [
['T1', -2, `x.levels[3].levelSize: ${LEVEL_SIZE_1}`],
['T11', -1, 'levelSize: average (not specified)'],
['R2', -1, `size: ${CELL_SIZE_1}`],
]
}, {
type: 'scatter',
name: 'left desc',
silent: true,
coordinateSystem: 'matrix',
symbolSize: 0,
symbolOffset: [0, 10],
label: {show: true, overflow: 'break', minMargin: 15},
labelLine: {show: true},
labelLayout: {x: '1%', width: 110, moveOverlap: 'shiftY'},
encode: {label: [0, 1, 2]},
data: [
[-3, 'A', `y.levelSize: ${LEVEL_SIZE_2}`],
[-2, 'A3', `y.levelSize: ${LEVEL_SIZE_2}`],
[-1, 'A31', `y.levels[4].levelSize: ${LEVEL_SIZE_3}`],
[-1, 'D', `size: ${CELL_SIZE_2}`],
[-4, 'E', `y.levels[2].levelSize: ${LEVEL_SIZE_4}`]
]
},
{
type: 'line',
xAxisId: 'aa',
yAxisId: 'aa',
data: [[11, 22], [33, 44], [55, 66]],
}, {
type: 'bar',
xAxisId: 'bb',
yAxisId: 'bb',
data: [987, 583, 671],
}]
};
var chart = testHelper.create(echarts, 'main_layout', {
title: [
'Locator testing.',
'scatter, cartesian, with Matrix.',
'cell merging: should display **on the center** of the merged cell.',
'click on cell to call convertFromPixel - especially on span cell.',
'click on corner should correct.',
'tooltip can be displayed for text (consider overflow).',
],
height: 500,
option: option,
inputsStyle: 'compact',
inputs: [
{
text: 'matrix.x show:',
type: 'select',
values: [true, false],
onchange() {
_xShowing = this.value;
chart.setOption({
matrix: {
x: {show: _xShowing},
},
});
updateCaseView();
}
},
{
text: 'matrix.y show:',
type: 'select',
values: [true, false],
onchange() {
_yShowing = this.value;
chart.setOption({
matrix: {
y: {show: _yShowing},
},
});
updateCaseView();
}
},
{
text: 'convertFromPixel clamp:',
type: 'select',
options: [
{value: undefined}
].concat(Object.keys(MatrixClampOption).map(key => ({
text: key,
value: MatrixClampOption[key],
}))),
onchange() {
_convertFromPixelClampOpt = this.value;
updateCaseView();
},
},
{
type: 'select',
text: 'text overflow:',
values: ['truncate', 'break', 'none'],
onchange() {
_textOverflow = this.value;
chart.setOption({
matrix: {
x: {label: {overflow: _textOverflow}},
y: {label: {overflow: _textOverflow}},
body: {label: {overflow: _textOverflow}},
corner: {label: {overflow: _textOverflow}},
},
});
updateCaseView();
}
},
{
type: 'select',
text: 'switch style:',
values: Object.keys(MATRIX_BACKGROUND_STYLE_MAP),
onchange() {
const preset = MATRIX_BACKGROUND_STYLE_MAP[this.value];
chart.setOption({
matrix: {
backgroundStyle: preset.backgroundStyle,
x: {
itemStyle: preset.x.itemStyle,
}
}
});
updateCaseView();
}
},
{
type: 'select',
text: 'convertToPixel test cases:',
values: [
'do_nothing',
['R2', 'A31'],
['not_exists', 'A1'],
['S', Infinity],
[1, 3],
['R1', 'A'],
['R1', 'A2'],
['R1', 'B4'],
['R1', 'B2'],
['R1', 'C'],
['R2', 'B3'],
],
onchange() {
const caseItem = this.value;
if (caseItem === 'do_nothing') {
return;
}
_convertToPointCaseItem = this.value;
updateCaseView();
}
},
]
});
function updateCaseView() {
if (!_convertToPointCaseItem) {
return;
}
const result = chart.convertToPixel({matrixIndex: 0}, _convertToPointCaseItem);
updateConvertToPixelResult(result);
}
function updateConvertToPixelResult(result) {
console.log(result);
chart.setOption({
title: {
text: 'convertToPixel result: ' + testHelper.printObject(result)
},
graphic: {
elements: [{
id: 'result',
type: 'circle',
shape: {
cx: result[0],
cy: result[1],
r: 20,
},
ignore: isNaN(result[0]) || isNaN(result[1]),
z: 1000,
style: {
stroke: 'red',
fill: null,
lineWidth: 5,
opacity: 0.8,
},
textContent: {
style: {
text: '⬅ convertToPixel result',
fill: 'red',
},
z: 1000,
},
textConfig: {
position: 'right'
},
}]
}
});
}
if (chart) {
chart.getZr().on('click', function (event) {
const point = [event.offsetX, event.offsetY];
let opt = null;
if (_convertFromPixelClampOpt != null) {
opt = {clamp: _convertFromPixelClampOpt};
}
const result = chart.convertFromPixel({matrixIndex: 0}, point, opt);
console.log('point', point, 'result', result);
chart.setOption({
title: {
text: 'convertFromPixel result: ' + testHelper.printObject(result)
}
});
});
}
});
</script>
<script>
require([
'echarts',
], function (echarts) {
var LEVEL_SIZE_1 = 15;
var LEVEL_SIZE_2 = 20;
var LEVEL_SIZE_3 = '10%';
var LEVEL_SIZE_4 = '0%';
var CELL_SIZE_1 = 30;
var CELL_SIZE_2 = 0;
var BODY_COMMON_COLOR = 'rgba(200, 150, 20, 0.1)';
var BODY_R2_A2_COLOR = 'rgba(200, 155, 0)';
var BODY_R1_B2_COLOR = 'rgba(200, 115, 200, 0.3)';
var X_COMMON_COLOR = 'rgba(22, 188, 212, 0.1)';
var X_T1_COLOR = 'rgba(12,122,250,0.8)';
var _bodyData = [
{
coord: ['R2', 'A3'],
mergeCells: true,
value: 'merged',
},
{
coord: ['R1', ['B4', 'C']],
mergeCells: true,
value: 'merged',
},
{
coord: [['R1', 'R2'], ['B2', 'B3']],
mergeCells: true,
value: 'merged',
},
{
coord: ['O', ['B2', 'not_exist']],
coordClamp: true,
mergeCells: true,
value: 'merged',
__expect: 'column O merged'
},
{
coord: ['T', ['A1', 'A31']],
mergeCells: true,
value: 'merged',
},
{
coord: ['S', null],
coordClamp: true,
mergeCells: true,
value: 'merged',
__expect: 'column S merged.'
},
];
var _cornerData = [
{
coord: [[-1, -2], -1],
mergeCells: true,
value: 'merged',
}
];
const _xData = [
{
value: 'R',
children: ['R1', {value: 'R2', size: CELL_SIZE_1}]
},
{
value: 'S'
},
{
value: 'T',
children: [
{
value: 'T1',
children: ['T11'],
}
]
},
'O',
'P',
];
const _yData = [
{
value: 'A',
children: ['A1', 'A2', {
value: 'A3',
children: ['A31', 'A32']
}]
}, {
value: 'B',
children: ['B1', 'B2', 'B3', 'B4']
}, {
value: 'C',
}, {
value: 'D',
}
];
const MatrixClampOption = {
none: 0,
all: 1,
body: 2,
corner: 3,
};
// --- state ------
let _xShowing = true;
let _yShowing = true;
let _convertToLayoutClampOpt = undefined;
let _ignoreMergeCells = undefined;
let _testCase = null;
// ----------------
function calcMeta() {
const xMeta = calcOneDim(_xData);
const yMeta = calcOneDim(_yData);
function calcOneDim(xyData) {
let levelCount = 0;
let leafCount = 0;
travel(xyData, 0, 0);
function travel(list, locatorStart, level) {
levelCount = Math.max(levelCount, level);
leafCount = Math.max(leafCount, locatorStart);
if (!list) {
return;
}
list.forEach((item, idx) => {
travel(item.children, locatorStart + idx, level + 1);
});
}
return {levelCount, leafCount};
}
const xUnitCount = xMeta.leafCount + (_yShowing ? yMeta.levelCount : 0);
const yUnitCount = yMeta.leafCount + (_xShowing ? xMeta.levelCount : 0);
return {xUnitCount, yUnitCount};
}
var option;
option = {
backgroundColor: '#eee',
tooltip: {},
title: {
text: '',
right: 'center',
},
matrix: [{
// matrix 0
right: 10,
bottom: 10,
width: 180,
height: 80,
x: {
data: ['X1', 'X2', 'X3'],
},
y: {
data: ['Y1', 'Y2', 'Y3', 'Y4'],
},
body: {
data: [{
coord: [[0, 2], [1, 2]],
value: 'should be right-bottom',
mergeCells: true,
}]
},
}, {
// matrix 1
id: 'main_matrix',
right: 10,
left: 230,
top: 50,
bottom: 120,
tooltip: {
show: true,
formatter(params) {
return params.name;
}
},
x: {
label: {
},
itemStyle: {
color: X_COMMON_COLOR
},
levels: [null, {levelSize: LEVEL_SIZE_1}],
data: _xData
},
y: {
levelSize: 40,
data: _yData,
},
body: {
data: _bodyData,
label: {
},
itemStyle: {
color: BODY_COMMON_COLOR
}
},
corner: {
data: _cornerData,
itemStyle: {
borderWidth: 1,
},
}
}],
series: [{
type: 'scatter',
coordinateSystem: 'matrix',
matrixIndex: 1,
symbolSize: 30,
data: [
['R1', 'A1', 10], ['R2', 'A1', 20], ['R1', 'A2', 30]
],
label: {
show: true,
formatter: params => {
return params.data[2];
}
}
}],
graphic: {
elements: [{
left: 5,
y: 5,
id: 'info_bodyData',
type: 'text',
style: {
text: 'Check body cell merge and style:\n' + testHelper.printObject(_bodyData, {lineBreakMaxColumn: 40}),
fontSize: 7,
}
}, {
left: 140,
y: 5,
id: 'info_cornerData',
type: 'text',
style: {
text: 'Check corner cell merge and style:\n' + testHelper.printObject(_cornerData, {lineBreakMaxColumn: 40}),
fontSize: 7,
}
}, {
id: 'result_convertToLayout',
type: 'rect',
shape: {x: 0, y: 0, width: 0, height: 0},
ignore: true,
silent: true,
style: {
fill: 'rgba(210,20,100,0.3)',
stroke: 'rgba(210,20,100,0.8)',
lineWidth: 3,
}
}, {
id: 'result_assertionFailure',
type: 'text',
ignore: true,
silent: true,
left: 10,
bottom: 10,
style: {
text: 'Some Case Failed',
fill: 'red',
fontSize: 20,
}
}]
},
};
var chart = testHelper.create(echarts, 'main_edge_cases', {
title: [
'Edge cases.',
'Test both when **show/hide** matrix.x/y; different **clamp**; **ignoreCellMerge** or not.',
'drag to resize to test cell border alignment',
'(must not affect by subpixel optimize or rounding error)',
],
height: 350,
option: option,
inputsStyle: 'compact',
draggable: true,
inputs: [
{
text: 'matrix.x show:',
type: 'select',
values: [true, false],
onchange() {
_xShowing = this.value;
chart.setOption({
matrix: {
id: 'main_matrix',
x: {show: _xShowing},
},
});
updateCaseView();
}
},
{
text: 'matrix.y show:',
type: 'select',
values: [true, false],
onchange() {
_yShowing = this.value;
chart.setOption({
matrix: {
id: 'main_matrix',
y: {show: _yShowing},
},
});
updateCaseView();
}
},
{
text: 'convertToLayout clamp:',
type: 'select',
options: [
{value: undefined}
].concat(Object.keys(MatrixClampOption).map(key => ({
text: key,
value: MatrixClampOption[key],
}))),
onchange() {
_convertToLayoutClampOpt = this.value;
updateCaseView();
},
},
{
text: 'ignoreMergeCells:',
type: 'select',
values: [undefined, false, true],
onchange() {
_ignoreMergeCells = this.value;
updateCaseView();
},
},
{
type: 'br',
},
{
type: 'select',
text: 'convertToLayout test cases:',
options: [{value: 'do_nothing'}].concat([
{
input: [],
expectDefault: {
rectNaN: {x: true, y: true, width: true, height: true},
matrixXYLocatorRange: [[NaN, NaN], [NaN, NaN]]
}
},
{
input: ['R2', null],
expectDefault: {
rectNaN: {y: true, height: true},
matrixXYLocatorRange: [[1, 1], [NaN, NaN]]
}
},
{
input: [['S', 'O'], NaN],
expectDefault: {
rectNaN: {y: true, height: true},
matrixXYLocatorRange: [[2, 4], [NaN, NaN]]
}
},
{
input: [['R'], NaN],
expectDefault: {
rectNaN: {y: true, height: true},
matrixXYLocatorRange: [[0, 1], [NaN, NaN]]
}
},
{
input: [NaN, 'A31'],
expectDefault: {
rectNaN: {x: true, width: true},
matrixXYLocatorRange: [[NaN, NaN], [2, 2]]
}
},
{
input: [undefined, ['A32', 'B3']],
expectDefault: {
rectNaN: {x: true, width: true},
matrixXYLocatorRange: [[NaN, NaN], [3, 6]]
}
},
{
input: [null, 'B'],
expectDefault: {
rectNaN: {x: true, width: true},
matrixXYLocatorRange: [[NaN, NaN], [4, 7]]
}
},
{
input: ['S', 'A32'],
expectDefault: {
rectNaN: {},
matrixXYLocatorRange: [[2, 2], [0, 9]]
}
},
{
input: ['T', 'B1'],
expectDefault: {
rectNaN: {},
matrixXYLocatorRange: [[3, 3], [4, 4]]
}
},
{
input: [[-1, 1], [-1, 2]],
expectDefault: {
rectNaN: {},
matrixXYLocatorRange: [[-2, 1], [-1, 3]]
}
},
{
input: ['R', -2],
expectDefault: {
rectNaN: {},
matrixXYLocatorRange: [[0, 1], [-2, -2]]
}
},
].map(item => ({
text: testHelper.printObject(item.input),
value: item,
}))),
onchange() {
if (this.value === 'do_nothing') {
return;
}
_testCase = this.value;
updateCaseView();
} // End of onchange
} // End of convertToLayout test cases
]
});
function updateCaseView() {
performTest(function (assert) {
if (!_testCase) {
return;
}
const {input, expectDefault} = _testCase;
const shouldBeClampped = !(
_convertToLayoutClampOpt == null || _convertToLayoutClampOpt === MatrixClampOption.none
);
const isDefaultCase = !shouldBeClampped && !_ignoreMergeCells;
const meta = calcMeta();
let opt = undefined;
if (_convertToLayoutClampOpt != null) {
opt = opt || {};
opt.clamp = _convertToLayoutClampOpt;
}
if (_ignoreMergeCells != null) {
opt = opt || {};
opt.ignoreMergeCells = _ignoreMergeCells;
}
const result = chart.convertToLayout({matrixIndex: 1}, input, opt);
console.log('Call convertToLayout', 'input:', input, 'opt:', opt, 'result:', result);
assert(testHelper.getType(result) === 'object');
assert(testHelper.getType(result.rect) === 'object');
assert(testHelper.getType(result.rect.x) === 'number');
assert(testHelper.getType(result.rect.y) === 'number');
assert(testHelper.getType(result.rect.width) === 'number');
assert(testHelper.getType(result.rect.height) === 'number');
assert(testHelper.getType(result.matrixXYLocatorRange) === 'array');
assert(testHelper.getType(result.matrixXYLocatorRange[0]) === 'array');
assert(testHelper.getType(result.matrixXYLocatorRange[1]) === 'array');
assert(testHelper.getType(result.matrixXYLocatorRange[0][0]) === 'number');
assert(testHelper.getType(result.matrixXYLocatorRange[0][1]) === 'number');
assert(testHelper.getType(result.matrixXYLocatorRange[1][0]) === 'number');
assert(testHelper.getType(result.matrixXYLocatorRange[1][1]) === 'number');
['x', 'y', 'width', 'height'].forEach(prop => {
if (isDefaultCase) {
if (expectDefault.rectNaN[prop]) {
assert(eqNaN(result.rect[prop]));
}
else {
assert(isFinite(result.rect[prop]));
}
}
else if (shouldBeClampped) {
assert(isFinite(result.rect[prop]));
}
});
if (isDefaultCase) {
assert(numEq(expectDefault.matrixXYLocatorRange[0][0], result.matrixXYLocatorRange[0][0]));
assert(numEq(expectDefault.matrixXYLocatorRange[0][1], result.matrixXYLocatorRange[0][1]));
assert(numEq(expectDefault.matrixXYLocatorRange[1][0], result.matrixXYLocatorRange[1][0]));
assert(numEq(expectDefault.matrixXYLocatorRange[1][1], result.matrixXYLocatorRange[1][1]));
}
return result;
});
function performTest(cb) {
let testFailed = false;
function assert(condition) {
if (!condition) {
testFailed = true;
console.error('assertion failed', new Error());
}
}
let result;
try {
result = cb(assert);
}
catch (err) {
testFailed = true;
console.error(err);
}
const COVER_SIZE = 10000; // Just a big enough number.
let indicatorShape = {x: 0, y: 0, width: 0, height: 0};
if (result) {
indicatorShape = {};
indicatorShape.x = eqNaN(result.rect.x) ? -COVER_SIZE / 2 : result.rect.x;
indicatorShape.y = eqNaN(result.rect.y) ? -COVER_SIZE / 2 : result.rect.y;
indicatorShape.width = eqNaN(result.rect.width) ? COVER_SIZE : result.rect.width;
indicatorShape.height = eqNaN(result.rect.height) ? COVER_SIZE : result.rect.height;;
}
chart.setOption({
graphic: {
elements: [{
id: 'result_convertToLayout',
shape: indicatorShape,
ignore: testFailed,
}, {
id: 'result_assertionFailure',
ignore: !testFailed,
}]
},
});
}
}
function eqNaN(value) {
return value !== value;
}
function numEq(expect, actual) {
return eqNaN(expect)
? eqNaN(actual)
: expect === actual;
}
});
</script>
</body>
</html>