@@ -9,12 +9,11 @@ var helpers = require('@src/components/legend/helpers');
9
9
var anchorUtils = require ( '@src/components/legend/anchor_utils' ) ;
10
10
11
11
var d3 = require ( 'd3' ) ;
12
- var fail = require ( '../assets/fail_test' ) ;
12
+ var failTest = require ( '../assets/fail_test' ) ;
13
13
var delay = require ( '../assets/delay' ) ;
14
14
var createGraphDiv = require ( '../assets/create_graph_div' ) ;
15
15
var destroyGraphDiv = require ( '../assets/destroy_graph_div' ) ;
16
16
17
-
18
17
describe ( 'legend defaults' , function ( ) {
19
18
'use strict' ;
20
19
@@ -538,7 +537,7 @@ describe('legend relayout update', function() {
538
537
. then ( function ( ) {
539
538
expect ( d3 . selectAll ( 'g.legend' ) . size ( ) ) . toBe ( 1 ) ;
540
539
} )
541
- . catch ( fail )
540
+ . catch ( failTest )
542
541
. then ( done ) ;
543
542
} ) ;
544
543
@@ -575,7 +574,7 @@ describe('legend relayout update', function() {
575
574
} ) . then ( function ( ) {
576
575
assertLegendStyle ( 'rgb(0, 0, 255)' , 'rgb(255, 0, 0)' , 10 ) ;
577
576
} )
578
- . catch ( fail )
577
+ . catch ( failTest )
579
578
. then ( done ) ;
580
579
} ) ;
581
580
} ) ;
@@ -907,7 +906,7 @@ describe('legend interaction', function() {
907
906
. then ( function ( ) {
908
907
assertVisible ( gd , [ true , true , true , true ] ) ;
909
908
} )
910
- . catch ( fail )
909
+ . catch ( failTest )
911
910
. then ( done ) ;
912
911
} ) ;
913
912
} ) ;
@@ -1009,7 +1008,7 @@ describe('legend interaction', function() {
1009
1008
{ target : 2 , value : { name : 'hoo' } }
1010
1009
] ) ;
1011
1010
assertLabels ( [ 'boo~~~' , '1 (trace 1)' , 'hoo ' , ' ' , '4 (trace 1)' ] ) ;
1012
- } ) . catch ( fail ) . then ( done ) ;
1011
+ } ) . catch ( failTest ) . then ( done ) ;
1013
1012
} ) ;
1014
1013
} ) ;
1015
1014
@@ -1035,9 +1034,13 @@ describe('legend interaction', function() {
1035
1034
} ;
1036
1035
}
1037
1036
1037
+ function extractVisibilities ( data ) {
1038
+ return data . map ( function ( trace ) { return trace . visible ; } ) ;
1039
+ }
1040
+
1038
1041
function assertVisible ( expectation ) {
1039
1042
return function ( ) {
1040
- var actual = gd . _fullData . map ( function ( trace ) { return trace . visible ; } ) ;
1043
+ var actual = extractVisibilities ( gd . _fullData ) ;
1041
1044
expect ( actual ) . toEqual ( expectation ) ;
1042
1045
} ;
1043
1046
}
@@ -1056,15 +1059,15 @@ describe('legend interaction', function() {
1056
1059
. then ( assertVisible ( [ false , 'legendonly' , true ] ) )
1057
1060
. then ( click ( 0 ) )
1058
1061
. then ( assertVisible ( [ false , true , true ] ) )
1059
- . catch ( fail ) . then ( done ) ;
1062
+ . catch ( failTest ) . then ( done ) ;
1060
1063
} ) ;
1061
1064
1062
1065
it ( 'clicking once toggles true -> legendonly' , function ( done ) {
1063
1066
Promise . resolve ( )
1064
1067
. then ( assertVisible ( [ false , 'legendonly' , true ] ) )
1065
1068
. then ( click ( 1 ) )
1066
1069
. then ( assertVisible ( [ false , 'legendonly' , 'legendonly' ] ) )
1067
- . catch ( fail ) . then ( done ) ;
1070
+ . catch ( failTest ) . then ( done ) ;
1068
1071
} ) ;
1069
1072
1070
1073
it ( 'double-clicking isolates a visible trace ' , function ( done ) {
@@ -1073,14 +1076,14 @@ describe('legend interaction', function() {
1073
1076
. then ( assertVisible ( [ false , true , true ] ) )
1074
1077
. then ( click ( 0 , 2 ) )
1075
1078
. then ( assertVisible ( [ false , true , 'legendonly' ] ) )
1076
- . catch ( fail ) . then ( done ) ;
1079
+ . catch ( failTest ) . then ( done ) ;
1077
1080
} ) ;
1078
1081
1079
1082
it ( 'double-clicking an isolated trace shows all non-hidden traces' , function ( done ) {
1080
1083
Promise . resolve ( )
1081
1084
. then ( click ( 0 , 2 ) )
1082
1085
. then ( assertVisible ( [ false , true , true ] ) )
1083
- . catch ( fail ) . then ( done ) ;
1086
+ . catch ( failTest ) . then ( done ) ;
1084
1087
} ) ;
1085
1088
} ) ;
1086
1089
@@ -1110,7 +1113,7 @@ describe('legend interaction', function() {
1110
1113
. then ( assertVisible ( [ false , 'legendonly' , true , 'legendonly' ] ) )
1111
1114
. then ( click ( 1 ) )
1112
1115
. then ( assertVisible ( [ false , true , true , true ] ) )
1113
- . catch ( fail ) . then ( done ) ;
1116
+ . catch ( failTest ) . then ( done ) ;
1114
1117
} ) ;
1115
1118
1116
1119
it ( 'isolates legendgroups as a whole' , function ( done ) {
@@ -1119,7 +1122,7 @@ describe('legend interaction', function() {
1119
1122
. then ( assertVisible ( [ false , true , 'legendonly' , true ] ) )
1120
1123
. then ( click ( 1 , 2 ) )
1121
1124
. then ( assertVisible ( [ false , true , true , true ] ) )
1122
- . catch ( fail ) . then ( done ) ;
1125
+ . catch ( failTest ) . then ( done ) ;
1123
1126
} ) ;
1124
1127
} ) ;
1125
1128
@@ -1152,7 +1155,7 @@ describe('legend interaction', function() {
1152
1155
it ( 'computes the initial visibility correctly' , function ( done ) {
1153
1156
Promise . resolve ( )
1154
1157
. then ( assertVisible ( [ false , true , true , true , true , true , true , true ] ) )
1155
- . catch ( fail ) . then ( done ) ;
1158
+ . catch ( failTest ) . then ( done ) ;
1156
1159
} ) ;
1157
1160
1158
1161
it ( 'toggles the visibility of a non-groupby trace in the presence of groupby traces' , function ( done ) {
@@ -1161,7 +1164,7 @@ describe('legend interaction', function() {
1161
1164
. then ( assertVisible ( [ false , true , 'legendonly' , true , true , true , true , true ] ) )
1162
1165
. then ( click ( 1 ) )
1163
1166
. then ( assertVisible ( [ false , true , true , true , true , true , true , true ] ) )
1164
- . catch ( fail ) . then ( done ) ;
1167
+ . catch ( failTest ) . then ( done ) ;
1165
1168
} ) ;
1166
1169
1167
1170
it ( 'toggles the visibility of the first group in a groupby trace' , function ( done ) {
@@ -1170,7 +1173,7 @@ describe('legend interaction', function() {
1170
1173
. then ( assertVisible ( [ false , 'legendonly' , true , true , true , true , true , true ] ) )
1171
1174
. then ( click ( 0 ) )
1172
1175
. then ( assertVisible ( [ false , true , true , true , true , true , true , true ] ) )
1173
- . catch ( fail ) . then ( done ) ;
1176
+ . catch ( failTest ) . then ( done ) ;
1174
1177
} ) ;
1175
1178
1176
1179
it ( 'toggles the visibility of the third group in a groupby trace' , function ( done ) {
@@ -1179,7 +1182,7 @@ describe('legend interaction', function() {
1179
1182
. then ( assertVisible ( [ false , true , true , true , 'legendonly' , true , true , true ] ) )
1180
1183
. then ( click ( 3 ) )
1181
1184
. then ( assertVisible ( [ false , true , true , true , true , true , true , true ] ) )
1182
- . catch ( fail ) . then ( done ) ;
1185
+ . catch ( failTest ) . then ( done ) ;
1183
1186
} ) ;
1184
1187
1185
1188
it ( 'double-clicking isolates a non-groupby trace' , function ( done ) {
@@ -1188,7 +1191,7 @@ describe('legend interaction', function() {
1188
1191
. then ( assertVisible ( [ false , true , 'legendonly' , 'legendonly' , 'legendonly' , 'legendonly' , 'legendonly' , 'legendonly' ] ) )
1189
1192
. then ( click ( 0 , 2 ) )
1190
1193
. then ( assertVisible ( [ false , true , true , true , true , true , true , true ] ) )
1191
- . catch ( fail ) . then ( done ) ;
1194
+ . catch ( failTest ) . then ( done ) ;
1192
1195
} ) ;
1193
1196
1194
1197
it ( 'double-clicking isolates a groupby trace' , function ( done ) {
@@ -1197,7 +1200,239 @@ describe('legend interaction', function() {
1197
1200
. then ( assertVisible ( [ false , 'legendonly' , true , 'legendonly' , 'legendonly' , 'legendonly' , 'legendonly' , 'legendonly' ] ) )
1198
1201
. then ( click ( 1 , 2 ) )
1199
1202
. then ( assertVisible ( [ false , true , true , true , true , true , true , true ] ) )
1200
- . catch ( fail ) . then ( done ) ;
1203
+ . catch ( failTest ) . then ( done ) ;
1204
+ } ) ;
1205
+ } ) ;
1206
+
1207
+ describe ( 'custom legend click/doubleclick handlers' , function ( ) {
1208
+ var fig , to ;
1209
+
1210
+ beforeEach ( function ( ) {
1211
+ fig = Lib . extendDeep ( { } , require ( '@mocks/0.json' ) ) ;
1212
+ } ) ;
1213
+
1214
+ afterEach ( function ( ) {
1215
+ clearTimeout ( to ) ;
1216
+ } ) ;
1217
+
1218
+ function setupFail ( ) {
1219
+ to = setTimeout ( function ( ) {
1220
+ fail ( 'did not trigger plotly_legendclick' ) ;
1221
+ } , 2 * DBLCLICKDELAY ) ;
1222
+ }
1223
+
1224
+ it ( 'should call custom click handler before default handler' , function ( done ) {
1225
+ Plotly . newPlot ( gd , fig ) . then ( function ( ) {
1226
+ var gotCalled = false ;
1227
+
1228
+ gd . on ( 'plotly_legendclick' , function ( d ) {
1229
+ gotCalled = true ;
1230
+ expect ( extractVisibilities ( d . fullData ) ) . toEqual ( [ true , true , true ] ) ;
1231
+ expect ( extractVisibilities ( gd . _fullData ) ) . toEqual ( [ true , true , true ] ) ;
1232
+ } ) ;
1233
+ gd . on ( 'plotly_restyle' , function ( ) {
1234
+ expect ( extractVisibilities ( gd . _fullData ) ) . toEqual ( [ true , 'legendonly' , true ] ) ;
1235
+ if ( gotCalled ) done ( ) ;
1236
+ } ) ;
1237
+ setupFail ( ) ;
1238
+ } )
1239
+ . then ( click ( 1 , 1 ) )
1240
+ . catch ( failTest ) ;
1241
+ } ) ;
1242
+
1243
+ it ( 'should call custom doubleclick handler before default handler' , function ( done ) {
1244
+ Plotly . newPlot ( gd , fig ) . then ( function ( ) {
1245
+ var gotCalled = false ;
1246
+
1247
+ gd . on ( 'plotly_legenddoubleclick' , function ( d ) {
1248
+ gotCalled = true ;
1249
+ expect ( extractVisibilities ( d . fullData ) ) . toEqual ( [ true , true , true ] ) ;
1250
+ expect ( extractVisibilities ( gd . _fullData ) ) . toEqual ( [ true , true , true ] ) ;
1251
+ } ) ;
1252
+ gd . on ( 'plotly_restyle' , function ( ) {
1253
+ expect ( extractVisibilities ( gd . _fullData ) ) . toEqual ( [ 'legendonly' , true , 'legendonly' ] ) ;
1254
+ if ( gotCalled ) done ( ) ;
1255
+ } ) ;
1256
+ setupFail ( ) ;
1257
+ } )
1258
+ . then ( click ( 1 , 2 ) )
1259
+ . catch ( failTest ) ;
1260
+ } ) ;
1261
+
1262
+ it ( 'should not call default click handler if custom handler return *false*' , function ( done ) {
1263
+ Plotly . newPlot ( gd , fig ) . then ( function ( ) {
1264
+ gd . on ( 'plotly_legendclick' , function ( d ) {
1265
+ Plotly . relayout ( gd , 'title' , 'just clicked on trace #' + d . curveNumber ) ;
1266
+ return false ;
1267
+ } ) ;
1268
+ gd . on ( 'plotly_relayout' , function ( d ) {
1269
+ expect ( typeof d ) . toBe ( 'object' ) ;
1270
+ expect ( d . title ) . toBe ( 'just clicked on trace #2' ) ;
1271
+ done ( ) ;
1272
+ } ) ;
1273
+ gd . on ( 'plotly_restyle' , function ( ) {
1274
+ fail ( 'should not have triggered plotly_restyle' ) ;
1275
+ } ) ;
1276
+ setupFail ( ) ;
1277
+ } )
1278
+ . then ( click ( 2 , 1 ) )
1279
+ . catch ( failTest ) ;
1280
+ } ) ;
1281
+
1282
+ it ( 'should not call default doubleclick handle if custom handler return *false*' , function ( done ) {
1283
+ Plotly . newPlot ( gd , fig ) . then ( function ( ) {
1284
+ gd . on ( 'plotly_legenddoubleclick' , function ( d ) {
1285
+ Plotly . relayout ( gd , 'title' , 'just double clicked on trace #' + d . curveNumber ) ;
1286
+ return false ;
1287
+ } ) ;
1288
+ gd . on ( 'plotly_relayout' , function ( d ) {
1289
+ expect ( typeof d ) . toBe ( 'object' ) ;
1290
+ expect ( d . title ) . toBe ( 'just double clicked on trace #0' ) ;
1291
+ done ( ) ;
1292
+ } ) ;
1293
+ gd . on ( 'plotly_restyle' , function ( ) {
1294
+ fail ( 'should not have triggered plotly_restyle' ) ;
1295
+ } ) ;
1296
+ setupFail ( ) ;
1297
+ } )
1298
+ . then ( click ( 0 , 2 ) )
1299
+ . catch ( failTest ) ;
1300
+ } ) ;
1301
+ } ) ;
1302
+
1303
+ describe ( 'legend click/doubleclick event data' , function ( ) {
1304
+ function _assert ( act , exp ) {
1305
+ for ( var k in exp ) {
1306
+ if ( k === 'event' || k === 'node' ) {
1307
+ expect ( act [ k ] ) . toBeDefined ( ) ;
1308
+ } else if ( k === 'group' ) {
1309
+ expect ( act [ k ] ) . toEqual ( exp [ k ] ) ;
1310
+ } else {
1311
+ expect ( act [ k ] ) . toBe ( exp [ k ] , 'key ' + k ) ;
1312
+ }
1313
+ }
1314
+
1315
+ expect ( Object . keys ( act ) . length )
1316
+ . toBe ( Object . keys ( exp ) . length , '# of keys' ) ;
1317
+ }
1318
+
1319
+ function clickAndCheck ( clickArg , exp ) {
1320
+ Lib . extendFlat ( exp , {
1321
+ event : true ,
1322
+ node : true ,
1323
+ data : gd . data ,
1324
+ layout : gd . layout ,
1325
+ frames : gd . _transitionData . _frames ,
1326
+ config : gd . _context ,
1327
+ fullData : gd . _fullData ,
1328
+ fullLayout : gd . _fullLayout
1329
+ } ) ;
1330
+
1331
+ var evtName = {
1332
+ 1 : 'plotly_legendclick' ,
1333
+ 2 : 'plotly_legenddoubleclick'
1334
+ } [ clickArg [ 1 ] ] ;
1335
+
1336
+ return new Promise ( function ( resolve , reject ) {
1337
+ var hasBeenCalled = false ;
1338
+
1339
+ var to = setTimeout ( function ( ) {
1340
+ reject ( 'did not trigger ' + evtName ) ;
1341
+ } , 2 * DBLCLICKDELAY ) ;
1342
+
1343
+ function done ( ) {
1344
+ if ( hasBeenCalled ) {
1345
+ clearTimeout ( to ) ;
1346
+ resolve ( ) ;
1347
+ }
1348
+ }
1349
+
1350
+ gd . once ( evtName , function ( d ) {
1351
+ hasBeenCalled = true ;
1352
+ _assert ( d , exp ) ;
1353
+ } ) ;
1354
+
1355
+ gd . once ( 'plotly_restyle' , done ) ;
1356
+ gd . once ( 'plotly_relayout' , done ) ;
1357
+
1358
+ click ( clickArg [ 0 ] , clickArg [ 1 ] ) ( ) ;
1359
+ } ) ;
1360
+ }
1361
+
1362
+ it ( 'should have correct keys (base case)' , function ( done ) {
1363
+ Plotly . newPlot ( gd , [ {
1364
+ x : [ 1 , 2 , 3 , 4 , 5 ] ,
1365
+ y : [ 1 , 2 , 1 , 2 , 3 ]
1366
+ } ] , {
1367
+ showlegend : true
1368
+ } )
1369
+ . then ( function ( ) {
1370
+ return clickAndCheck ( [ 0 , 1 ] , {
1371
+ curveNumber : 0 ,
1372
+ expandedIndex : 0
1373
+ } ) ;
1374
+ } )
1375
+ . then ( function ( ) {
1376
+ return clickAndCheck ( [ 0 , 2 ] , {
1377
+ curveNumber : 0 ,
1378
+ expandedIndex : 0
1379
+ } ) ;
1380
+ } )
1381
+ . catch ( failTest )
1382
+ . then ( done ) ;
1383
+ } ) ;
1384
+
1385
+ it ( 'should have correct keys (groupby case)' , function ( done ) {
1386
+ Plotly . newPlot ( gd , [ {
1387
+ x : [ 1 , 2 , 3 , 4 , 5 ] ,
1388
+ y : [ 1 , 2 , 1 , 2 , 3 ] ,
1389
+ transforms : [ {
1390
+ type : 'groupby' ,
1391
+ groups : [ 'a' , 'b' , 'b' , 'a' , 'b' ]
1392
+ } ]
1393
+ } , {
1394
+ x : [ 1 , 2 , 3 , 4 , 5 ] ,
1395
+ y : [ 1 , 2 , 1 , 2 , 3 ] ,
1396
+ } ] )
1397
+ . then ( function ( ) {
1398
+ return clickAndCheck ( [ 1 , 1 ] , {
1399
+ curveNumber : 0 ,
1400
+ expandedIndex : 1 ,
1401
+ group : 'b'
1402
+ } ) ;
1403
+ } )
1404
+ . then ( function ( ) {
1405
+ return clickAndCheck ( [ 2 , 2 ] , {
1406
+ curveNumber : 1 ,
1407
+ expandedIndex : 2
1408
+ } ) ;
1409
+ } )
1410
+ . catch ( failTest )
1411
+ . then ( done ) ;
1412
+ } ) ;
1413
+
1414
+ it ( 'should have correct keys (pie case)' , function ( done ) {
1415
+ Plotly . newPlot ( gd , [ {
1416
+ type : 'pie' ,
1417
+ labels : [ 'A' , 'B' , 'C' , 'D' ] ,
1418
+ values : [ 1 , 2 , 1 , 3 ]
1419
+ } ] )
1420
+ . then ( function ( ) {
1421
+ return clickAndCheck ( [ 0 , 1 ] , {
1422
+ curveNumber : 0 ,
1423
+ expandedIndex : 0 ,
1424
+ label : 'D'
1425
+ } ) ;
1426
+ } )
1427
+ . then ( function ( ) {
1428
+ return clickAndCheck ( [ 2 , 2 ] , {
1429
+ curveNumber : 0 ,
1430
+ expandedIndex : 0 ,
1431
+ label : 'A'
1432
+ } ) ;
1433
+ } )
1434
+ . catch ( failTest )
1435
+ . then ( done ) ;
1201
1436
} ) ;
1202
1437
} ) ;
1203
1438
} ) ;
0 commit comments