Skip to content

Parallel Categories (parcats) trace type for multi dimensional categorical data #2963

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 51 commits into from
Oct 1, 2018
Merged
Changes from 1 commit
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
1a8a0f0
Initial parcats trace implementation
Nov 27, 2017
406cd24
color attribute fixes for rebase on 1.39.3
jonmmease Jul 27, 2018
ee7fd17
lint fixes
jonmmease Jul 27, 2018
3e43ef3
Remove customHovers, replace with loneHover
jonmmease Aug 7, 2018
0c9c75f
Bring back customHovers
jonmmease Aug 7, 2018
7b75100
Renamed `parcats.marker` -> `parcats.line`
jonmmease Aug 7, 2018
d2c5ae8
Use plots/domain and handleDomainDefaults
jonmmease Aug 8, 2018
a34dafa
Rename displayInd -> displayindex
jonmmease Aug 8, 2018
71e212b
Convert to simplified colorbar logic
jonmmease Aug 8, 2018
6797a83
Remove maxDimensionCount check
jonmmease Aug 9, 2018
2c14168
Cleanup supplyDefaults and add visible dimension property
jonmmease Aug 9, 2018
c8e3cc9
Added support for dimensions with visible=false
jonmmease Aug 10, 2018
6a5c20e
Fixed failing test (needed to rename displayInd -> displayindex)
jonmmease Aug 10, 2018
22346d0
Added mock with color hovermode
jonmmease Aug 10, 2018
3680084
Replace tooltip with hoverinfo
Aug 15, 2018
2d07f4d
Added `arrangement` property that is very similar to the sankey trace
Aug 15, 2018
7f90fc1
WIP towards categoryorder/categoryarray/categorylabels
Aug 16, 2018
5e60062
Full support for categoryorder, categoryarray, and categorylabels
Aug 17, 2018
66c90fa
Fixed tests to use new `categoryorder`, `categoryarray`, `categorylab…
Aug 20, 2018
69f6922
Add 'dimension' hovermode that uses multi-hoverlabel logic
Aug 20, 2018
f2aa9b9
Added labelfont and categorylabelfont top-level attributes
Aug 21, 2018
4eb5317
Review / cleanup attribute descriptions
Aug 21, 2018
a897388
Add `counts` attribute to parcats_hovermode_dimension mock
Aug 21, 2018
98d76ee
Refactor dimension and category dragging tests and test arrangements
Aug 23, 2018
66f21fe
Add tests for clicking on category and path with/without hoverinfo skip
Aug 23, 2018
30ca2ec
Add tests for clicking on category and path with hovermode 'color'
Sep 1, 2018
69311fc
Implement plotly_unhover events
Sep 1, 2018
b3b73a6
Add tests for hovering on category and paths
Sep 1, 2018
fed71e7
eslint fixes
Sep 1, 2018
9361cc4
Fix up attribute description specifications
Sep 1, 2018
6ca2d66
Fix test comments
Sep 1, 2018
2a51ca9
Added new baseline images for parcats mocks
Sep 4, 2018
948bf0a
Fix headers (it *was* 2017 when I started this!)
Sep 4, 2018
b1ef6c9
markerColorscale no longer used
Sep 5, 2018
5a19499
Rename categorylabels -> ticktext and categorylabelfont -> tickfont
Sep 5, 2018
1f6a2e0
Update baseline image for parcats_reordered (Added "One"/"Two" labels)
Sep 7, 2018
340ae53
eslint fixes
Sep 7, 2018
9b66bee
Support Rich text / Latex in category labels (ticktext)
Sep 10, 2018
870ff82
eslint fixes
Sep 11, 2018
7e4a6ad
Handle line.color as TypedArray
Sep 12, 2018
e7edebd
hovermode -> hoveron
Sep 13, 2018
20bc21b
Baseline images for hovermode -> hoveron conversion
Sep 13, 2018
273d2d0
Hide unsupported top-level properties from plot-schema
Sep 24, 2018
e8ded39
Merge remote-tracking branch 'upstream/master' into parcats
Sep 24, 2018
4bc3d35
Fix plotschema tests in the presence of potentially undefined schema …
Sep 24, 2018
2684d69
Fix path tooltip direction when graph div is offset from left margin
Sep 25, 2018
267c750
Increase default font size slightly
Sep 25, 2018
2100d96
Remove redundant require('./hover') operations
Sep 28, 2018
eba1b4a
Cleanup line defaults logic
Sep 28, 2018
4117612
Create `parcats_grid_subplots` mock with 4 grid-based subplots
Sep 28, 2018
99f9a47
Use layout.colorway[0] as the default color for parcats traces
jonmmease Sep 28, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add tests for hovering on category and paths
  • Loading branch information
Jon M. Mease committed Sep 1, 2018
commit b3b73a6d76f23e1d4482c9d75fb919b64a0525cb
328 changes: 307 additions & 21 deletions test/jasmine/tests/parcats_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1428,24 +1428,310 @@ describe('Click events with hovermode color', function() {
});
});

// To Test
// -------

// ### Hovering
// - Hover down to top middle category, and top path.
// - [ ] Path hover label
// - [ ] Category hover label for 'category', 'color', and 'dimension', `hovermode`
// - [ ] No category hover label for 'none', 'skip' `hovermode
// - [ ] Events emitted on path hover
// - [ ] Events emitted on category hover in 'category', 'color', 'dimension', and 'none' `hovermode`
// - [ ] No events emitted on category or path in 'skip' `hovermode`
// In each case, check hoverinfo text

// ### Test that properties have the desired effect on models
// - [ ] visible
// - [ ] counts
// - [ ] bundlecolors
// - [ ] sortpaths
//
//
// ### Test Font styles ###
describe('Hover events', function() {

// Variable declarations
// ---------------------
// ### Trace level ###
var gd,
mock;

// Fixtures
// --------
beforeEach(function() {
gd = createGraphDiv();
mock = Lib.extendDeep({}, require('@mocks/parcats_basic_freeform.json'));
});

afterEach(destroyGraphDiv);

it('hover and unhover should fire on category', function(done) {

var hoverData,
unhoverData,
mouseY0,
mouseX0;

Plotly.newPlot(gd, mock)
.then(function() {
/** @type {ParcatsViewModel} */
var parcatsViewModel = d3.select('g.trace.parcats').datum();

gd.on('plotly_hover', function(data) {
hoverData = data;
});

gd.on('plotly_unhover', function(data) {
unhoverData = data;
});

// Hover over top category of middle dimension (category "A")
var dimStartX = parcatsViewModel.dimensions[1].x;

mouseY0 = parcatsViewModel.y + parcatsViewModel.dimensions[1].categories[2].y + 10;
mouseX0 = parcatsViewModel.x + dimStartX + dimWidth / 2;

// Position mouse for start of drag
// --------------------------------
mouseEvent('mousemove', mouseX0, mouseY0);
mouseEvent('mouseover', mouseX0, mouseY0);
Lib.clearThrottle();
})
.then(delay(CALLBACK_DELAY))
.then(function() {
// Check that hover callback was called
expect(hoverData).toBeDefined();

// Check that the right points were reported
var pts = hoverData.points.sort(function(a, b) {
return a.pointNumber - b.pointNumber;
});
expect(pts).toEqual([
{curveNumber: 0, pointNumber: 4},
{curveNumber: 0, pointNumber: 5},
{curveNumber: 0, pointNumber: 8}]);

// Check that unhover is still undefined
expect(unhoverData).toBeUndefined();
})
.then(function(){
// Unhover
mouseEvent('mouseout', mouseX0, mouseY0);
Lib.clearThrottle();
})
.then(function(){
// Check that unhover callback was called
expect(unhoverData).toBeDefined();

// Check that the right points were reported
var pts = unhoverData.points.sort(function(a, b) {
return a.pointNumber - b.pointNumber;
});
expect(pts).toEqual([
{curveNumber: 0, pointNumber: 4},
{curveNumber: 0, pointNumber: 5},
{curveNumber: 0, pointNumber: 8}]);
})
.catch(failTest)
.then(done);
});

it('hover and unhover should fire on path', function(done) {

var hoverData,
unhoverData,
mouseY0,
mouseX0;

Plotly.newPlot(gd, mock)
.then(function() {
/** @type {ParcatsViewModel} */
var parcatsViewModel = d3.select('g.trace.parcats').datum();

gd.on('plotly_hover', function(data) {
hoverData = data;
});

gd.on('plotly_unhover', function(data) {
unhoverData = data;
});


var dimStartX = parcatsViewModel.dimensions[1].x;
mouseY0 = parcatsViewModel.y + parcatsViewModel.dimensions[1].categories[2].y + 10;
mouseX0 = parcatsViewModel.x + dimStartX + dimWidth + 10;

// Position mouse for start of drag
// --------------------------------
mouseEvent('mousemove', mouseX0, mouseY0);
mouseEvent('mouseover', mouseX0, mouseY0);
Lib.clearThrottle();
})
.then(delay(CALLBACK_DELAY))
.then(function() {
// Check that hover callback was called
expect(hoverData).toBeDefined();

// Check that the right points were reported
var pts = hoverData.points.sort(function(a, b) {
return a.pointNumber - b.pointNumber;
});
expect(pts).toEqual([
{curveNumber: 0, pointNumber: 5},
{curveNumber: 0, pointNumber: 8}]);

// Check that unhover is still undefined
expect(unhoverData).toBeUndefined();
})
.then(function(){
// Unhover
mouseEvent('mouseout', mouseX0, mouseY0);
Lib.clearThrottle();
})
.then(function(){
// Check that unhover callback was called
expect(unhoverData).toBeDefined();

// Check that the right points were reported
var pts = unhoverData.points.sort(function(a, b) {
return a.pointNumber - b.pointNumber;
});
expect(pts).toEqual([
{curveNumber: 0, pointNumber: 5},
{curveNumber: 0, pointNumber: 8}]);
})
.catch(failTest)
.then(done);
});
});

describe('Hover events with hovermode color', function() {

// Variable declarations
// ---------------------
// ### Trace level ###
var gd,
mock;

// Fixtures
// --------
beforeEach(function() {
gd = createGraphDiv();
mock = Lib.extendDeep({}, require('@mocks/parcats_hovermode_color.json'));
});

afterEach(destroyGraphDiv);

it('hover and unhover should fire on category hovermode color', function(done) {

var hoverData,
unhoverData,
mouseY0,
mouseX0;

Plotly.newPlot(gd, mock)
.then(function() {
/** @type {ParcatsViewModel} */
var parcatsViewModel = d3.select('g.trace.parcats').datum();

gd.on('plotly_hover', function(data) {
hoverData = data;
});

gd.on('plotly_unhover', function(data) {
unhoverData = data;
});

// Hover over top category of middle dimension (category "A")
var dimStartX = parcatsViewModel.dimensions[1].x;

mouseY0 = parcatsViewModel.y + parcatsViewModel.dimensions[1].categories[2].y + 10;
mouseX0 = parcatsViewModel.x + dimStartX + dimWidth / 2;

// Position mouse for start of drag
// --------------------------------
mouseEvent('mousemove', mouseX0, mouseY0);
mouseEvent('mouseover', mouseX0, mouseY0);
Lib.clearThrottle();
})
.then(delay(CALLBACK_DELAY))
.then(function() {
// Check that hover callback was called
expect(hoverData).toBeDefined();

// Check that the right points were reported
var pts = hoverData.points.sort(function(a, b) {
return a.pointNumber - b.pointNumber;
});
expect(pts).toEqual([
{curveNumber: 0, pointNumber: 5}]);

// Check that unhover is still undefined
expect(unhoverData).toBeUndefined();
})
.then(function(){
// Unhover
mouseEvent('mouseout', mouseX0, mouseY0);
Lib.clearThrottle();
})
.then(function(){
// Check that unhover callback was called
expect(unhoverData).toBeDefined();

// Check that the right points were reported
var pts = unhoverData.points.sort(function(a, b) {
return a.pointNumber - b.pointNumber;
});
expect(pts).toEqual([
{curveNumber: 0, pointNumber: 5}]);
})
.catch(failTest)
.then(done);
});

it('hover and unhover should fire on path hovermode color', function(done) {

var hoverData,
unhoverData,
mouseY0,
mouseX0;

Plotly.newPlot(gd, mock)
.then(function() {
/** @type {ParcatsViewModel} */
var parcatsViewModel = d3.select('g.trace.parcats').datum();

gd.on('plotly_hover', function(data) {
hoverData = data;
});

gd.on('plotly_unhover', function(data) {
unhoverData = data;
});


var dimStartX = parcatsViewModel.dimensions[1].x;
mouseY0 = parcatsViewModel.y + parcatsViewModel.dimensions[1].categories[2].y + 10;
mouseX0 = parcatsViewModel.x + dimStartX + dimWidth + 10;

// Position mouse for start of drag
// --------------------------------
mouseEvent('mousemove', mouseX0, mouseY0);
mouseEvent('mouseover', mouseX0, mouseY0);
Lib.clearThrottle();
})
.then(delay(CALLBACK_DELAY))
.then(function() {
// Check that hover callback was called
expect(hoverData).toBeDefined();

// Check that the right points were reported
var pts = hoverData.points.sort(function(a, b) {
return a.pointNumber - b.pointNumber;
});
expect(pts).toEqual([
{curveNumber: 0, pointNumber: 5}]);

// Check that unhover is still undefined
expect(unhoverData).toBeUndefined();
})
.then(function(){
// Unhover
mouseEvent('mouseout', mouseX0, mouseY0);
Lib.clearThrottle();
})
.then(function(){
// Check that unhover callback was called
expect(unhoverData).toBeDefined();

// Check that the right points were reported
var pts = unhoverData.points.sort(function(a, b) {
return a.pointNumber - b.pointNumber;
});
expect(pts).toEqual([
{curveNumber: 0, pointNumber: 5}]);
})
.catch(failTest)
.then(done);
});
});