mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Replace charting library Flotr2 with ChartJS using React. Fixes #3904
This commit is contained in:
committed by
Akshay Joshi
parent
5820b9521e
commit
f715373218
@@ -1,100 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2020, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import $ from 'jquery';
|
||||
import {Chart} from 'top/dashboard/static/js/charting';
|
||||
|
||||
describe('In charting related testcases', ()=> {
|
||||
let chartObj = undefined,
|
||||
chartDiv = undefined,
|
||||
options = {};
|
||||
|
||||
beforeEach(()=> {
|
||||
$('body').append(
|
||||
'<div id="charting-test-container"></div>'
|
||||
);
|
||||
chartDiv = $('#charting-test-container')[0];
|
||||
chartObj = new Chart(chartDiv, options);
|
||||
});
|
||||
|
||||
it('Return the correct container', ()=>{
|
||||
expect(chartObj.getContainer()).toEqual(chartDiv);
|
||||
});
|
||||
|
||||
it('Returns the container dimensions', ()=>{
|
||||
let dim = chartObj.getContainerDimensions();
|
||||
expect(dim.height).toBeDefined();
|
||||
expect(dim.width).toBeDefined();
|
||||
});
|
||||
|
||||
it('Check if options are set', ()=>{
|
||||
chartObj.setOptions({
|
||||
mouse: {
|
||||
track:true,
|
||||
},
|
||||
});
|
||||
|
||||
let opt = chartObj.getOptions();
|
||||
|
||||
expect(opt.mouse).toBeDefined();
|
||||
});
|
||||
|
||||
it('Check if options are set with mergeOptions false', ()=>{
|
||||
let overOpt = {
|
||||
mouse: {
|
||||
track:true,
|
||||
},
|
||||
};
|
||||
chartObj.setOptions(overOpt, false);
|
||||
|
||||
let newOptShouldBe = {...chartObj._defaultOptions, ...overOpt};
|
||||
|
||||
let opt = chartObj.getOptions();
|
||||
expect(JSON.stringify(opt)).toEqual(JSON.stringify(newOptShouldBe));
|
||||
});
|
||||
|
||||
it('Check if other data is set', ()=>{
|
||||
chartObj.setOtherData('some_val', 1);
|
||||
expect(chartObj._otherData['some_val']).toEqual(1);
|
||||
});
|
||||
|
||||
it('Check if other data is get', ()=>{
|
||||
chartObj.setOtherData('some_val', 1);
|
||||
expect(chartObj.getOtherData('some_val')).toEqual(1);
|
||||
});
|
||||
|
||||
it('Check if other data returns undefined for not set', ()=>{
|
||||
expect(chartObj.getOtherData('some_val_not_set')).toEqual(undefined);
|
||||
});
|
||||
|
||||
it('Check if isVisible returns correct', ()=>{
|
||||
let dimSpy = spyOn(chartObj, 'getContainerDimensions');
|
||||
|
||||
dimSpy.and.returnValue({
|
||||
height: 1, width: 1,
|
||||
});
|
||||
expect(chartObj.isVisible()).toEqual(true);
|
||||
dimSpy.and.stub();
|
||||
|
||||
dimSpy.and.returnValue({
|
||||
height: 0, width: 0,
|
||||
});
|
||||
expect(chartObj.isVisible()).toEqual(false);
|
||||
});
|
||||
|
||||
it('Check if isInPage returns correct', ()=>{
|
||||
expect(chartObj.isInPage()).toEqual(true);
|
||||
$('body').find('#charting-test-container').remove();
|
||||
expect(chartObj.isInPage()).toEqual(false);
|
||||
});
|
||||
|
||||
afterEach(()=>{
|
||||
$('body').find('#charting-test-container').remove();
|
||||
});
|
||||
});
|
||||
169
web/regression/javascript/dashboard/graphs_spec.js
Normal file
169
web/regression/javascript/dashboard/graphs_spec.js
Normal file
@@ -0,0 +1,169 @@
|
||||
import jasmineEnzyme from 'jasmine-enzyme';
|
||||
import React from 'react';
|
||||
import {mount} from 'enzyme';
|
||||
import '../helper/enzyme.helper';
|
||||
|
||||
import Graphs, {GraphsWrapper} from '../../../pgadmin/dashboard/static/js/Graphs';
|
||||
import {X_AXIS_LENGTH, POINT_SIZE, transformData, legendCallback,
|
||||
getStatsUrl, statsReducer} from '../../../pgadmin/dashboard/static/js/Graphs';
|
||||
|
||||
describe('Graphs.js', ()=>{
|
||||
it('transformData', ()=>{
|
||||
expect(transformData({'Label1': [], 'Label2': []}, 1)).toEqual({
|
||||
labels: [...Array(X_AXIS_LENGTH).keys()],
|
||||
datasets: [{
|
||||
label: 'Label1',
|
||||
data: [],
|
||||
borderColor: '#00BCD4',
|
||||
backgroundColor: '#00BCD4',
|
||||
pointHitRadius: POINT_SIZE,
|
||||
},{
|
||||
label: 'Label2',
|
||||
data: [],
|
||||
borderColor: '#9CCC65',
|
||||
backgroundColor: '#9CCC65',
|
||||
pointHitRadius: POINT_SIZE,
|
||||
}],
|
||||
refreshRate: 1,
|
||||
});
|
||||
});
|
||||
|
||||
it('legendCallback', ()=>{
|
||||
expect(legendCallback({
|
||||
id: 1,
|
||||
data: {
|
||||
datasets: [{
|
||||
label: 'Label1',
|
||||
backgroundColor: '#00BCD4',
|
||||
},{
|
||||
label: 'Label2',
|
||||
backgroundColor: '#9CCC65',
|
||||
}],
|
||||
},
|
||||
})).toEqual([
|
||||
'<div class="1-legend d-flex">',
|
||||
'<div class="legend-value"><span style="background-color:#00BCD4"> </span>',
|
||||
'<span class="legend-label">Label1</span>',
|
||||
'</div>',
|
||||
'<div class="legend-value"><span style="background-color:#9CCC65"> </span>',
|
||||
'<span class="legend-label">Label2</span>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
].join(''));
|
||||
});
|
||||
|
||||
describe('getStatsUrl', ()=>{
|
||||
it('for server', ()=>{
|
||||
expect(getStatsUrl(432, -1, ['chart1'])).toEqual('/dashboard/dashboard_stats/432?chart_names=chart1');
|
||||
});
|
||||
it('for database', ()=>{
|
||||
expect(getStatsUrl(432, 123, ['chart1'])).toEqual('/dashboard/dashboard_stats/432/123?chart_names=chart1');
|
||||
});
|
||||
it('for multiple graphs', ()=>{
|
||||
expect(getStatsUrl(432, 123, ['chart1', 'chart2'])).toEqual('/dashboard/dashboard_stats/432/123?chart_names=chart1,chart2');
|
||||
});
|
||||
});
|
||||
|
||||
describe('statsReducer', ()=>{
|
||||
it('with incoming no counter', ()=>{
|
||||
let state = {
|
||||
'Label1': [], 'Label2': [],
|
||||
};
|
||||
let action = {
|
||||
incoming: {
|
||||
'Label1': 1, 'Label2': 2,
|
||||
},
|
||||
};
|
||||
let newState = {
|
||||
'Label1': [1], 'Label2': [2],
|
||||
};
|
||||
state = statsReducer(state, action);
|
||||
expect(state).toEqual(newState);
|
||||
});
|
||||
|
||||
it('with incoming with counter', ()=>{
|
||||
let state = {
|
||||
'Label1': [1], 'Label2': [2],
|
||||
};
|
||||
let action = {
|
||||
incoming: {
|
||||
'Label1': 1, 'Label2': 3,
|
||||
},
|
||||
counter: true,
|
||||
counterData: {'Label1': 1, 'Label2': 2},
|
||||
};
|
||||
let newState = {
|
||||
'Label1': [0, 1], 'Label2': [1, 2],
|
||||
};
|
||||
state = statsReducer(state, action);
|
||||
expect(state).toEqual(newState);
|
||||
});
|
||||
|
||||
it('with reset', ()=>{
|
||||
let state = {
|
||||
'Label1': [0, 1], 'Label2': [1, 2],
|
||||
};
|
||||
let action = {
|
||||
reset: {
|
||||
'Label1': [2], 'Label2': [2],
|
||||
},
|
||||
};
|
||||
let newState = {
|
||||
'Label1': [2], 'Label2': [2],
|
||||
};
|
||||
state = statsReducer(state, action);
|
||||
expect(state).toEqual(newState);
|
||||
});
|
||||
});
|
||||
|
||||
describe('<Graphs /> component', ()=>{
|
||||
let graphComp = null;
|
||||
let sid = 1;
|
||||
let did = 1;
|
||||
beforeEach(()=>{
|
||||
jasmineEnzyme();
|
||||
let dashboardPref = {
|
||||
session_stats_refresh: 1,
|
||||
tps_stats_refresh: 1,
|
||||
ti_stats_refresh: 1,
|
||||
to_stats_refresh: 1,
|
||||
bio_stats_refresh: 1,
|
||||
show_graphs: true,
|
||||
graph_data_points: true,
|
||||
graph_mouse_track: true,
|
||||
};
|
||||
|
||||
graphComp = mount(<Graphs preferences={dashboardPref} sid={sid} did={did} enablePoll={false} pageVisible={true} />);
|
||||
});
|
||||
|
||||
it('GraphsWrapper is rendered', (done)=>{
|
||||
let found = graphComp.find(GraphsWrapper);
|
||||
expect(found.length).toBe(1);
|
||||
done();
|
||||
});
|
||||
|
||||
it('pollDelay is set', (done)=>{
|
||||
let found = graphComp.find('[data-testid="graph-poll-delay"]');
|
||||
expect(found).toHaveClassName('d-none');
|
||||
expect(found).toHaveText('1000');
|
||||
done();
|
||||
});
|
||||
|
||||
it('pollDelay on preference update', (done)=>{
|
||||
let dashboardPref = {
|
||||
session_stats_refresh: 5,
|
||||
tps_stats_refresh: 10,
|
||||
ti_stats_refresh: 5,
|
||||
to_stats_refresh: 10,
|
||||
bio_stats_refresh: 10,
|
||||
show_graphs: true,
|
||||
graph_data_points: true,
|
||||
graph_mouse_track: true,
|
||||
};
|
||||
graphComp.setProps({preferences: dashboardPref});
|
||||
let found = graphComp.find('[data-testid="graph-poll-delay"]');
|
||||
expect(found).toHaveText('5000');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
90
web/regression/javascript/dashboard/graphs_wrapper_spec.js
Normal file
90
web/regression/javascript/dashboard/graphs_wrapper_spec.js
Normal file
@@ -0,0 +1,90 @@
|
||||
import jasmineEnzyme from 'jasmine-enzyme';
|
||||
import React from 'react';
|
||||
import {mount} from 'enzyme';
|
||||
import '../helper/enzyme.helper';
|
||||
|
||||
import {GraphsWrapper, X_AXIS_LENGTH, POINT_SIZE} from '../../../pgadmin/dashboard/static/js/Graphs';
|
||||
|
||||
describe('<GraphsWrapper /> component', ()=>{
|
||||
let graphComp = null;
|
||||
let defaultStats = {
|
||||
labels: [...Array(X_AXIS_LENGTH).keys()],
|
||||
datasets: [{
|
||||
label: 'Label1',
|
||||
data: [],
|
||||
borderColor: '#00BCD4',
|
||||
backgroundColor: '#00BCD4',
|
||||
pointHitRadius: POINT_SIZE,
|
||||
},{
|
||||
label: 'Label2',
|
||||
data: [],
|
||||
borderColor: '#9CCC65',
|
||||
backgroundColor: '#9CCC65',
|
||||
pointHitRadius: POINT_SIZE,
|
||||
}],
|
||||
refreshRate: 1,
|
||||
};
|
||||
beforeEach(()=>{
|
||||
jasmineEnzyme();
|
||||
graphComp = mount(<GraphsWrapper sessionStats={defaultStats}
|
||||
tpsStats={defaultStats}
|
||||
tiStats={defaultStats}
|
||||
toStats={defaultStats}
|
||||
bioStats={defaultStats}
|
||||
errorMsg={null}
|
||||
showTooltip={true}
|
||||
showDataPoints={true}
|
||||
isDatabase={false} />);
|
||||
});
|
||||
|
||||
it('graph containers are rendered', (done)=>{
|
||||
let found = graphComp.find('.card.dashboard-graph');
|
||||
expect(found.length).toBe(5);
|
||||
done();
|
||||
});
|
||||
|
||||
it('graph headers are correct', (done)=>{
|
||||
let found = graphComp.find('.card.dashboard-graph');
|
||||
expect(found.at(0)).toIncludeText('Server sessions');
|
||||
expect(found.at(1)).toIncludeText('Transactions per second');
|
||||
expect(found.at(2)).toIncludeText('Tuples in');
|
||||
expect(found.at(3)).toIncludeText('Tuples out');
|
||||
expect(found.at(4)).toIncludeText('Block I/O');
|
||||
done();
|
||||
});
|
||||
|
||||
it('graph headers when database', (done)=>{
|
||||
let found = graphComp.find('.card.dashboard-graph');
|
||||
graphComp.setProps({isDatabase: true});
|
||||
expect(found.at(0)).toIncludeText('Database sessions');
|
||||
done();
|
||||
});
|
||||
|
||||
it('graph body has the canvas', (done)=>{
|
||||
let found = graphComp.find('.card.dashboard-graph .dashboard-graph-body canvas');
|
||||
expect(found.at(0).length).toBe(1);
|
||||
expect(found.at(1).length).toBe(1);
|
||||
expect(found.at(2).length).toBe(1);
|
||||
expect(found.at(3).length).toBe(1);
|
||||
expect(found.at(4).length).toBe(1);
|
||||
done();
|
||||
});
|
||||
|
||||
it('graph body shows the error', (done)=>{
|
||||
graphComp.setProps({errorMsg: 'Some error occurred'});
|
||||
let found = graphComp.find('.card.dashboard-graph .dashboard-graph-body .chart-wrapper');
|
||||
expect(found.at(0)).toHaveClassName('d-none');
|
||||
expect(found.at(1)).toHaveClassName('d-none');
|
||||
expect(found.at(2)).toHaveClassName('d-none');
|
||||
expect(found.at(3)).toHaveClassName('d-none');
|
||||
expect(found.at(4)).toHaveClassName('d-none');
|
||||
|
||||
found = graphComp.find('.card.dashboard-graph .dashboard-graph-body .pg-panel-error.pg-panel-message');
|
||||
expect(found.at(0)).toIncludeText('Some error occurred');
|
||||
expect(found.at(1)).toIncludeText('Some error occurred');
|
||||
expect(found.at(2)).toIncludeText('Some error occurred');
|
||||
expect(found.at(3)).toIncludeText('Some error occurred');
|
||||
expect(found.at(4)).toIncludeText('Some error occurred');
|
||||
done();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user