blob: 110a9beeb2b0bbfc609c359368529a9be9e16d30 [file] [log] [blame]
<!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 style="
height: 1207px;
margin: 0;
padding: 20px;
background: #eee;
overflow: hidden;
box-sizing: border-box;
"
>
This is a placeholder for y coord matching the visual test due to the visual test migration.
<br>
Scroll down to check the test case below.
<br>
↓ ↓ ↓
</div>
<div id="main_self_layout"></div>
<div id="main_dim_data_edge_cases"></div>
<script>
var option;
require([
'echarts'
], function (echarts) {
const layoutList = [
{
layout: {
left: 10,
bottom: 10,
width: 250,
height: 50,
},
expect: 'left-bottom',
},
{
layout: {
right: 10,
bottom: 10,
width: 250,
height: 50,
},
expect: 'right-bottom'
},
{
layout: {
},
expect: 'default place'
},
];
option = {
backgroundColor: '#eee',
matrix: [
// Layout test (r/l/t/b/w/h)
...layoutList.map(item => ({
...item.layout,
backgroundStyle: {
color: '#ddd'
},
x: {show: false, data: ['X1']},
y: {show: false, data: ['Y1']},
body: {
label: {fontSize: 10},
data: [{
coord: [0, 0],
value: `expect matrix on ${item.expect} due to\nl/r/t/b/w/h settings are:\n`
+ JSON.stringify(item.layout)
}]
}
})),
// z-order test
...[{
matrixLayout: {
top: 10,
left: 10,
width: 300,
height: 50,
},
borderZ2: undefined,
}, {
matrixLayout: {
top: 'center',
left: 10,
width: 300,
height: 50,
},
borderZ2: 500,
}].map(({matrixLayout, borderZ2}) => ({
...matrixLayout,
backgroundStyle: {
color: 'yellow',
borderColor: 'orange',
borderWidth: 5,
shadowColor: '#111',
shadowBlur: 15,
},
borderZ2,
x: {
data: ['X1', 'X2', 'X3'],
dividerLineStyle: {
color: 'rgb(0,200,200)',
width: 5,
},
},
y: {
data: ['Y1', 'Y2', 'Y3'],
dividerLineStyle: {
color: 'rgb(100,150,150)',
width: 5,
},
},
body: {
label: {
fontSize: 10,
},
itemStyle: {
borderWidth: 1,
borderColor: 'blue'
},
data: [{
coord: [0, 0],
itemStyle: {
borderColor: 'red',
borderWidth: 3
},
value: 'red border',
}, {
coord: [[1, 2], 0],
itemStyle: {
borderColor: 'green',
borderWidth: 3
},
mergeCells: true,
value: 'green border',
}, {
coord: [[1, 2], 2],
mergeCells: true,
label: {
position: 'insideRight'
},
value: `borderZ2: ${borderZ2}`,
}]
},
z: 10
}))
]
};
var chart = testHelper.create(echarts, 'main_self_layout', {
height: 200,
title: [
'matrix self layout test',
'z-index test'
],
option: option,
});
});
</script>
<script>
require([
'echarts',
], function (echarts) {
const MatrixClampOption = {
none: 0,
all: 1,
body: 2,
corner: 3,
};
function makeMatrixOption({x, y, xLevels, yLevels}, {xShow, yShow}) {
return {
top: 90,
bottom: 100,
left: 160,
x: {
show: !!xShow,
data: x,
levels: xLevels ? xLevels : undefined,
itemStyle: {color: '#111'},
label: {color: '#eee'},
},
y: {
show: !!yShow,
data: y,
levels: yLevels ? yLevels : undefined,
itemStyle: {color: '#111'},
label: {color: '#eee'},
},
corner: {
itemStyle: {color: '#333'},
label: {color: '#eee'},
}
};
}
function makeFailedOption(failed) {
return {
id: 'success_or_fail',
type: 'text',
ignore: failed == null,
style: {
text: failed ? 'Case Failed' : 'Case Succeeded',
fontSize: 18,
fill: failed ? 'red' : 'green',
}
}
}
const _matrixXYDataMap = {
test_d: {
desc: 'Different subtree have duplicated text, expect display the original text',
data: {
x: [{value: 'a', children: ['o', 'p', 'q']}, {value: 'b', children: ['o', 'p', 'q']}],
y: [{value: 'M', children: [new Date(), /a/]}]
},
testList: [{
testType: 'convertToLayout',
cases: [{
input: ['o', 'Y1'],
expect: {matrixXYLocatorRange: [[0, 0], [1, 1]]},
}, {
input: [3, 0],
expect: {matrixXYLocatorRange: [[3, 3], [0, 0]]},
}, {
input: [7, 0],
expect: {matrixXYLocatorRange: [[3, 5], [0, 0]]},
}, {
input: [7, 0],
opt: {clamp: MatrixClampOption.body},
expect: {matrixXYLocatorRange: [[3, 5], [0, 0]]},
}]
}]
},
test_a: {
desc: 'matrix.y.data is empty array, expect no error.',
data: {
x: ['a', 'X2', null, 'd'],
y: [],
},
testList: [{
testType: 'convertToLayout',
cases: [{
input: ['X2', null],
expect: {matrixXYLocatorRange: [[1, 1], [NaN, NaN]]},
}, {
input: [null, 0],
expect: {matrixXYLocatorRange: [[NaN, NaN], [NaN, NaN]]},
}, {
input: [null, null],
opt: {clamp: MatrixClampOption.body},
expect: {matrixXYLocatorRange: [[0, 3], [NaN, NaN]]},
}]
}]
},
test_a2: {
desc: 'matrix.x.data is empty array, expect no error.',
data: {
x: [],
y: ['a', 'X2', null, 'd'],
},
},
test_b: {
desc: '[null] is allowed; number is illegal in matrix.x/y.data and replaced by auto-gen text.',
data: {
x: [null, null],
y: [1, 2, 3],
},
testList: [{
testType: 'convertToLayout',
cases: [{
input: ['X1', 0],
expect: {matrixXYLocatorRange: [[1, 1], [0, 0]]},
}, {
input: [-1, -1],
expect: {matrixXYLocatorRange: [[-1, -1], [-1, -1]]},
}, {
input: [null, null],
opt: {clamp: MatrixClampOption.body},
expect: {matrixXYLocatorRange: [[0, 1], [0, 2]]},
}, {
input: [null, null],
opt: {clamp: MatrixClampOption.corner},
expect: {matrixXYLocatorRange: [[-1, -1], [-1, -1]]},
}, {
input: [0, 0],
opt: {clamp: MatrixClampOption.corner},
expect: {matrixXYLocatorRange: [[-1, -1], [-1, -1]]},
}]
}]
},
test_c: {
desc: 'No matrix.x/y.data, expect no error',
data: {
x: [],
y: [],
},
testList: [{
testType: 'convertToLayout',
cases: [{
input: [0, 0],
expect: {matrixXYLocatorRange: [[NaN, NaN], [NaN, NaN]]},
}, {
input: [null, null],
opt: {clamp: MatrixClampOption.body},
expect: {matrixXYLocatorRange: [[NaN, NaN], [NaN, NaN]]},
}]
}]
},
test_e: {
desc: 'All col/row width specified but not touch or overflow the bounary',
data: {
x: [{value: 'a1', size: 30}, {value: 'a2', size: 30}],
y: [{value: 'b1', size: 300}, {value: 'b2', size: 300}],
yLevels: [{levelSize: 50}]
},
},
test_f: {
desc: 'collect all from series.data (has null/NaN/undefined/illegal, expect display)',
data: {
x: undefined,
y: undefined,
seriesData: [
['fruit', undefined, 1223],
['bread', 'good', 323],
['milk', 'good', 142],
[null, 'medium', 63],
['bread', 'medium', 91],
['milk', 9999, 45],
['fruit', NaN, 55],
['bread', 'bad', 15],
['milk', 'bad', 53],
],
},
},
test_g: {
desc: 'no series.data and no matrix.x/y',
data: {
x: undefined,
y: undefined,
seriesData: [],
},
},
};
let _ctx = {
xyData: 'test_d',
testResult: null, // {result: unknown, failed: boolean}
xShow: true,
yShow: true,
convertFromPixelOpt: null,
};
function updateView() {
const option = {
matrix: makeMatrixOption(_matrixXYDataMap[_ctx.xyData].data, _ctx),
series: {
data: _matrixXYDataMap[_ctx.xyData].data.seriesData
},
};
chart.setOption(option, {replaceMerge: 'matrix'});
chart.setOption({
graphic: {
elements: [{
id: 'convert_result',
style: {
text: _ctx.testResult ? _ctx.testResult.result : '',
}
}, {
id: 'desc_text',
style: {
text: '--- expect ---\n' + (_matrixXYDataMap[_ctx.xyData].desc || '')
+ '\n--- current matrix data ---\n'
+ testHelper.printObject(
{
x: {
data: _matrixXYDataMap[_ctx.xyData].data.x,
levels: _matrixXYDataMap[_ctx.xyData].data.xLevels,
},
y: {
data: _matrixXYDataMap[_ctx.xyData].data.y,
levels: _matrixXYDataMap[_ctx.xyData].data.yLevels,
},
},
{lineBreakMaxColumn: 150}
)
+ '\n--- current series data ---\n' + (
_matrixXYDataMap[_ctx.xyData].data.seriesData
? testHelper.printObject(
_matrixXYDataMap[_ctx.xyData].data.seriesData,
{lineBreakMaxColumn: 30}
)
: 'undefined'
)
}
},
makeFailedOption(_ctx.testResult ? !!_ctx.testResult.failed : undefined)
]
}
});
}
const option = {
tooltip: {},
backgroundColor: '#aee',
matrix: makeMatrixOption(_matrixXYDataMap[_ctx.xyData].data, _ctx),
series: {
type: 'scatter',
coordinateSystem: 'matrix',
symbolSize: 20,
encode: {label: 2},
label: {show: true},
data: _matrixXYDataMap[_ctx.xyData].data.seriesData
},
graphic: {
elements: [{
bottom: 5,
left: 'center',
id: 'convert_result',
type: 'text',
style: {
text: '',
fill: 'blue',
fontSize: 11,
},
silent: true
}, {
left: 5,
top: 5,
id: 'desc_text',
type: 'text',
style: {
fontSize: 12,
fill: '#333',
},
silent: true
}, {
right: 5,
top: 5,
id: 'success_or_fail',
type: 'text',
style: {
fontSize: 20,
fill: 'red',
},
silent: true
}]
}
};
var chart = testHelper.create(echarts, 'main_dim_data_edge_cases', {
title: [
'edge case',
'**click** on matrix inside and outside to test clamp.'
],
option: option,
height: 400,
inputsStyle: 'compact',
inputs: [{
text: 'test cases:',
type: 'select',
options: Object.keys(_matrixXYDataMap).map(key => {
let text = _matrixXYDataMap[key].desc;
const MAX_STR = 100;
if (text.length > MAX_STR) {
text = text.slice(0, MAX_STR) + ' ...';
}
return {text: text, value: key};
}),
onchange() {
const key = this.value;
_ctx.xyData = key;
_ctx.testResult = null;
chart.__testHelper.switchGroup(key);
updateView();
}
}, {
type: 'br',
}, {
text: 'matrix.x show:',
type: 'select',
values: [true, false],
onchange() {
_ctx.xShow = this.value;
updateView();
}
}, {
text: 'matrix.y show:',
type: 'select',
values: [true, false],
onchange() {
_ctx.yShow = this.value;
updateView();
}
}, {
text: 'convertFromPixel opt:',
type: 'select',
options: [
{value: undefined},
{text: 'clamp body', value: {clamp: MatrixClampOption.body}},
{text: 'clamp corner', value: {clamp: MatrixClampOption.corner}},
{text: 'clamp all', value: {clamp: MatrixClampOption.all}},
{text: 'clamp none', value: {clamp: MatrixClampOption.none}},
],
onchange() {
_ctx.convertFromPixelOpt = this.value;
}
}, {
type: 'groupset',
inputsStyle: 'compact',
inputsHeight: 70,
groups: Object.keys(_matrixXYDataMap).map(key => {
const textList = _matrixXYDataMap[key].testList || [];
const inputs = [];
textList.forEach(testItem => {
if (testItem.testType === 'convertToLayout') {
const cases = testItem.cases;
cases.forEach(caseItem => {
inputs.push({
text: `convertToLayout(${testHelper.printObject(caseItem.input)}, ${testHelper.printObject(caseItem.opt)})`,
onclick() {
let expect = caseItem.expect;
let failed = false;
let actual;
try {
actual = chart.convertToLayout({matrixIndex: 0}, caseItem.input, caseItem.opt);
console.log(actual);
if (!numEq(expect.matrixXYLocatorRange[0][0], actual.matrixXYLocatorRange[0][0])
|| !numEq(expect.matrixXYLocatorRange[0][1], actual.matrixXYLocatorRange[0][1])
|| !numEq(expect.matrixXYLocatorRange[1][0], actual.matrixXYLocatorRange[1][0])
|| !numEq(expect.matrixXYLocatorRange[1][1], actual.matrixXYLocatorRange[1][1])
) {
failed = true;
}
}
catch (err) {
console.error(err);
failed = true;
}
const result = 'convertToLayout result: ' + testHelper.printObject(actual);
_ctx.testResult = {result, failed};
updateView();
}
});
});
}
else {
throw new Error('illegal');
}
});
return {
id: key,
text: '[' + key + '] test cases:',
inputs,
};
})
}] // End of inputs
});
if (chart) {
updateView();
chart.getZr().on('click', function (event) {
const point = [event.offsetX, event.offsetY];
const data = chart.convertFromPixel({matrixIndex: 0}, point, _ctx.convertFromPixelOpt);
const layout = chart.convertToLayout({matrixIndex: 0}, data);
_ctx.testResult = {
result: 'convertFromPixel result: ' + testHelper.printObject(data) + '\n'
+ 'Then use it convertToLayout result: ' + testHelper.printObject(layout),
failed: false
};
updateView();
});
}
});
function eqNaN(value) {
return value !== value;
}
function numEq(expect, actual) {
return eqNaN(expect)
? eqNaN(actual)
: expect === actual;
}
</script>
</body>
</html>