diff --git a/src/processor/dataStack.ts b/src/processor/dataStack.ts index f83c7f90f6..48ce66ec19 100644 --- a/src/processor/dataStack.ts +++ b/src/processor/dataStack.ts @@ -150,8 +150,9 @@ function calculateStack(stackInfoList: StackInfo[]) { stackStrategy === 'all' // single stack group || (stackStrategy === 'positive' && val > 0) || (stackStrategy === 'negative' && val < 0) - || (stackStrategy === 'samesign' && sum >= 0 && val > 0) // All positive stack - || (stackStrategy === 'samesign' && sum <= 0 && val < 0) // All negative stack + // For 'samesign', 0 is not stacked. + || (stackStrategy === 'samesign' && sum > 0 && val > 0) // All positive stack + || (stackStrategy === 'samesign' && sum < 0 && val < 0) // All negative stack ) { // The sum has to be very small to be affected by the // floating arithmetic problem. An incorrect result will probably diff --git a/test/ut/jest.config.cjs b/test/ut/jest.config.cjs index 5ca8031953..0eac19b025 100644 --- a/test/ut/jest.config.cjs +++ b/test/ut/jest.config.cjs @@ -46,7 +46,8 @@ module.exports = { '**/spec/data/*.test.ts', '**/spec/model/*.test.ts', '**/spec/scale/*.test.ts', - '**/spec/util/*.test.ts' + '**/spec/util/*.test.ts', + '**/spec/processor/*.test.ts' ], moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, { prefix: '/' diff --git a/test/ut/spec/processor/dataStack.test.ts b/test/ut/spec/processor/dataStack.test.ts new file mode 100644 index 0000000000..0730bd2437 --- /dev/null +++ b/test/ut/spec/processor/dataStack.test.ts @@ -0,0 +1,102 @@ +import { createChart, getECModel } from '../../core/utHelper'; +import { EChartsType } from '@/src/echarts.all'; + +describe('processor/dataStack', function() { + let chart: EChartsType; + beforeEach(function () { + chart = createChart(); + }); + + afterEach(function () { + chart.dispose(); + }); + + it('should not stack on zero value with samesign strategy', function() { + chart.setOption({ + xAxis: { data: ['a', 'b', 'c'] }, + yAxis: { type: 'value' }, + series: [{ + type: 'line', + data: [10, 20, 30], + stack: 'total', + stackStrategy: 'samesign' + }, { + type: 'line', + data: [5, 0, 10], + stack: 'total', + stackStrategy: 'samesign' + }] + }); + + const ecModel = getECModel(chart); + const seriesModels = ecModel.getSeries(); + const resultData = seriesModels[1].getData(); + const stackResultDim = resultData.getCalculationInfo('stackResultDimension'); + const stackedOverDim = resultData.getCalculationInfo('stackedOverDimension'); + + // with the fix, stackResultDimension at index 1 should be 0, and stackedOverDimension should be NaN + expect(resultData.get(stackResultDim, 1)).toEqual(0); + expect(resultData.get(stackedOverDim, 1)).toBeNaN(); + }); + + it('should not stack on zero value when stacked on zero value', function() { + chart.setOption({ + xAxis: { data: ['a', 'b', 'c'] }, + yAxis: { type: 'value' }, + series: [{ + type: 'line', + data: [10, 0, 30], + stack: 'total', + stackStrategy: 'samesign' + }, { + type: 'line', + data: [5, 0, 10], + stack: 'total', + stackStrategy: 'samesign' + }] + }); + + const ecModel = getECModel(chart); + const seriesModels = ecModel.getSeries(); + const resultData = seriesModels[1].getData(); + const stackResultDim = resultData.getCalculationInfo('stackResultDimension'); + const stackedOverDim = resultData.getCalculationInfo('stackedOverDimension'); + + expect(resultData.get(stackResultDim, 1)).toEqual(0); + expect(resultData.get(stackedOverDim, 1)).toBeNaN(); + }); + + it('should correctly stack when a zero value series is in the middle', function() { + chart.setOption({ + xAxis: { data: ['a', 'b', 'c'] }, + yAxis: { type: 'value' }, + series: [{ + type: 'line', + data: [10, 20, 30], + stack: 'total', + stackStrategy: 'samesign' + }, { + type: 'line', + data: [5, 0, -10], + stack: 'total', + stackStrategy: 'samesign' + }, { + type: 'line', + data: [5, 5, 5], + stack: 'total', + stackStrategy: 'samesign' + }] + }); + + const ecModel = getECModel(chart); + const seriesModels = ecModel.getSeries(); + const resultData = seriesModels[2].getData(); + const stackResultDim = resultData.getCalculationInfo('stackResultDimension'); + const stackedOverDim = resultData.getCalculationInfo('stackedOverDimension'); + + // series 3 should be stacked on series 1, because series 2 has a zero and a negative value. + expect(resultData.get(stackResultDim, 1)).toEqual(25); + expect(resultData.get(stackedOverDim, 1)).toEqual(20); + }); +}); +