|
| 1 | +var Plotly = require('@lib/index'); |
| 2 | +var constants = require('@src/plots/smith/constants'); |
1 | 3 | var Smith = require('@src/plots/smith');
|
| 4 | +var Lib = require('@src/lib'); |
| 5 | + |
| 6 | +var d3Select = require('../../strict-d3').select; |
| 7 | +var d3SelectAll = require('../../strict-d3').selectAll; |
| 8 | + |
| 9 | +var destroyGraphDiv = require('../assets/destroy_graph_div'); |
| 10 | +var createGraphDiv = require('../assets/create_graph_div'); |
| 11 | + |
| 12 | +var mouseEvent = require('../assets/mouse_event'); |
2 | 13 |
|
3 | 14 | describe('Test smith plot defaults:', function() {
|
4 | 15 | var layoutOut;
|
@@ -43,4 +54,325 @@ describe('Test smith plot defaults:', function() {
|
43 | 54 | expect(imag.type).toBe('linear');
|
44 | 55 | expect(real.type).toBe('linear');
|
45 | 56 | });
|
| 57 | + |
| 58 | + it('should propagate axis *color* settings', function() { |
| 59 | + _supply({ |
| 60 | + smith: { |
| 61 | + imaginaryaxis: {color: 'red'}, |
| 62 | + realaxis: {color: 'blue'} |
| 63 | + } |
| 64 | + }); |
| 65 | + |
| 66 | + expect(layoutOut.smith.imaginaryaxis.linecolor).toBe('red'); |
| 67 | + expect(layoutOut.smith.imaginaryaxis.gridcolor).toBe('rgb(255, 153, 153)', 'blend by 60% with bgcolor'); |
| 68 | + |
| 69 | + expect(layoutOut.smith.realaxis.title.font.color).toBe('blue'); |
| 70 | + expect(layoutOut.smith.realaxis.linecolor).toBe('blue'); |
| 71 | + expect(layoutOut.smith.realaxis.gridcolor).toBe('rgb(153, 153, 255)', 'blend by 60% with bgcolor'); |
| 72 | + }); |
| 73 | + |
| 74 | + it('should coerce hoverformat even for `visible: false` axes', function() { |
| 75 | + _supply({ |
| 76 | + smith: { |
| 77 | + realaxis: { |
| 78 | + visible: false, |
| 79 | + hoverformat: 'g' |
| 80 | + }, |
| 81 | + imaginaryaxis: { |
| 82 | + visible: false, |
| 83 | + hoverformat: 'g' |
| 84 | + } |
| 85 | + } |
| 86 | + }, [{ |
| 87 | + type: 'scattersmith', |
| 88 | + re: [1, 2], |
| 89 | + im: [90, 180], |
| 90 | + visible: true, |
| 91 | + subplot: 'smith' |
| 92 | + }]); |
| 93 | + |
| 94 | + expect(layoutOut.smith.realaxis.hoverformat).toBe('g'); |
| 95 | + expect(layoutOut.smith.imaginaryaxis.hoverformat).toBe('g'); |
| 96 | + }); |
| 97 | +}); |
| 98 | + |
| 99 | +describe('Test relayout on smith subplots:', function() { |
| 100 | + afterEach(destroyGraphDiv); |
| 101 | + |
| 102 | + it('should be able to reorder axis layers when relayout\'ing *layer*', function(done) { |
| 103 | + var gd = createGraphDiv(); |
| 104 | + var fig = Lib.extendDeep({}, require('@mocks/zzz_smith_axes.json')); |
| 105 | + var dflt = constants.layerNames; |
| 106 | + |
| 107 | + function _assert(expected) { |
| 108 | + var actual = d3SelectAll('g.smith > .smithsublayer'); |
| 109 | + |
| 110 | + expect(actual.size()).toBe(expected.length, '# of layer'); |
| 111 | + |
| 112 | + actual.each(function(d, i) { |
| 113 | + var className = d3Select(this) |
| 114 | + .attr('class') |
| 115 | + .split('smithsublayer ')[1]; |
| 116 | + |
| 117 | + expect(className).toBe(expected[i], 'layer ' + i); |
| 118 | + }); |
| 119 | + } |
| 120 | + |
| 121 | + Plotly.newPlot(gd, fig).then(function() { |
| 122 | + _assert(dflt); |
| 123 | + return Plotly.relayout(gd, 'smith.realaxis.layer', 'below traces'); |
| 124 | + }) |
| 125 | + .then(function() { |
| 126 | + _assert([ |
| 127 | + 'draglayer', 'plotbg', 'angular-grid', 'radial-grid', |
| 128 | + 'radial-line', 'radial-axis', |
| 129 | + 'frontplot', |
| 130 | + 'angular-line', 'angular-axis' |
| 131 | + ]); |
| 132 | + return Plotly.relayout(gd, 'smith.imaginaryaxis.layer', 'below traces'); |
| 133 | + }) |
| 134 | + .then(function() { |
| 135 | + _assert([ |
| 136 | + 'draglayer', 'plotbg', 'angular-grid', 'radial-grid', |
| 137 | + 'angular-line', |
| 138 | + 'radial-line', |
| 139 | + 'angular-axis', |
| 140 | + 'radial-axis', |
| 141 | + 'frontplot' |
| 142 | + ]); |
| 143 | + return Plotly.relayout(gd, 'smith.realaxis.layer', 'above traces'); |
| 144 | + }) |
| 145 | + .then(function() { |
| 146 | + _assert([ |
| 147 | + 'draglayer', 'plotbg', 'angular-grid', 'radial-grid', |
| 148 | + 'angular-line', 'angular-axis', |
| 149 | + 'frontplot', |
| 150 | + 'radial-line', 'radial-axis' |
| 151 | + ]); |
| 152 | + return Plotly.relayout(gd, 'smith.imaginaryaxis.layer', null); |
| 153 | + }) |
| 154 | + .then(function() { |
| 155 | + _assert(dflt); |
| 156 | + }) |
| 157 | + .then(done, done.fail); |
| 158 | + }); |
| 159 | + |
| 160 | + it('should be able to toggle axis features', function(done) { |
| 161 | + var gd = createGraphDiv(); |
| 162 | + var fig = Lib.extendDeep({}, require('@mocks/zzz_smith_single.json')); |
| 163 | + |
| 164 | + function assertCnt(selector, expected, msg) { |
| 165 | + var sel = d3Select(gd).selectAll(selector); |
| 166 | + expect(sel.size()).toBe(expected, msg); |
| 167 | + } |
| 168 | + |
| 169 | + function assertDisplay(selector, expected, msg) { |
| 170 | + var sel = d3Select(gd).select(selector); |
| 171 | + |
| 172 | + if(!sel.size()) fail(selector + ' not found'); |
| 173 | + |
| 174 | + sel.each(function() { |
| 175 | + expect(d3Select(this).attr('display')).toBe(expected, msg); |
| 176 | + }); |
| 177 | + } |
| 178 | + |
| 179 | + function toggle(astr, vals, exps, selector, fn) { |
| 180 | + return function() { |
| 181 | + return Plotly.relayout(gd, astr, vals[0]).then(function() { |
| 182 | + fn(selector, exps[0], astr + ' ' + vals[0]); |
| 183 | + return Plotly.relayout(gd, astr, vals[1]); |
| 184 | + }) |
| 185 | + .then(function() { |
| 186 | + fn(selector, exps[1], astr + ' ' + vals[1]); |
| 187 | + return Plotly.relayout(gd, astr, vals[0]); |
| 188 | + }) |
| 189 | + .then(function() { |
| 190 | + fn(selector, exps[0], astr + ' ' + vals[0]); |
| 191 | + }); |
| 192 | + }; |
| 193 | + } |
| 194 | + |
| 195 | + Plotly.newPlot(gd, fig) |
| 196 | + .then(toggle( |
| 197 | + 'smith.realaxis.showline', |
| 198 | + [true, false], [null, 'none'], |
| 199 | + '.radial-line > line', assertDisplay |
| 200 | + )) |
| 201 | + .then(toggle( |
| 202 | + 'smith.realaxis.showgrid', |
| 203 | + [true, false], [null, 'none'], |
| 204 | + '.radial-grid', assertDisplay |
| 205 | + )) |
| 206 | + .then(toggle( |
| 207 | + 'smith.realaxis.showticklabels', |
| 208 | + [true, false], [5, 0], |
| 209 | + '.radial-axis > .realaxis2tick > text', assertCnt |
| 210 | + )) |
| 211 | + .then(toggle( |
| 212 | + 'smith.imaginaryaxis.showline', |
| 213 | + [true, false], [null, 'none'], |
| 214 | + '.angular-line > path', assertDisplay |
| 215 | + )) |
| 216 | + .then(toggle( |
| 217 | + 'smith.imaginaryaxis.showgrid', |
| 218 | + [true, false], [10, 0], |
| 219 | + '.angular-grid > path', assertCnt |
| 220 | + )) |
| 221 | + .then(toggle( |
| 222 | + 'smith.imaginaryaxis.showticklabels', |
| 223 | + [true, false], [12, 0], |
| 224 | + '.angular-axis > .imaginaryaxistick > text', assertCnt |
| 225 | + )) |
| 226 | + .then(done, done.fail); |
| 227 | + }); |
| 228 | + |
| 229 | + it('should clean up its framework, clip paths and info layers when getting deleted', function(done) { |
| 230 | + var gd = createGraphDiv(); |
| 231 | + var fig = Lib.extendDeep({}, require('@mocks/zzz_smith_fill.json')); |
| 232 | + var traces = Lib.extendDeep([], fig.data); |
| 233 | + var inds = traces.map(function(_, i) { return i; }); |
| 234 | + |
| 235 | + function _assert(exp) { |
| 236 | + expect(d3SelectAll('g.smith').size()).toBe(exp.subplot, '# subplot layer'); |
| 237 | + expect(d3SelectAll('g.g-smithtitle').size()).toBe(exp.rtitle, '# radial title'); |
| 238 | + |
| 239 | + var clipCnt = 0; |
| 240 | + d3SelectAll('clipPath').each(function() { |
| 241 | + if(/smith-for-traces/.test(this.id)) clipCnt++; |
| 242 | + }); |
| 243 | + expect(clipCnt).toBe(exp.clip, '# clip paths'); |
| 244 | + } |
| 245 | + |
| 246 | + Plotly.newPlot(gd, fig).then(function() { |
| 247 | + _assert({subplot: 1, clip: 1, rtitle: 1}); |
| 248 | + |
| 249 | + return Plotly.deleteTraces(gd, inds); |
| 250 | + }) |
| 251 | + .then(function() { |
| 252 | + _assert({subplot: 0, clip: 0, rtitle: 0}); |
| 253 | + |
| 254 | + return Plotly.addTraces(gd, traces); |
| 255 | + }) |
| 256 | + .then(function() { |
| 257 | + _assert({subplot: 1, clip: 1, rtitle: 1}); |
| 258 | + }) |
| 259 | + .then(done, done.fail); |
| 260 | + }); |
| 261 | +}); |
| 262 | + |
| 263 | +describe('Test smith interactions:', function() { |
| 264 | + var gd; |
| 265 | + var eventData; |
| 266 | + var eventCnts; |
| 267 | + |
| 268 | + var eventNames = [ |
| 269 | + 'plotly_hover', 'plotly_unhover', |
| 270 | + 'plotly_click', 'plotly_doubleclick', |
| 271 | + 'plotly_relayout' |
| 272 | + ]; |
| 273 | + |
| 274 | + beforeEach(function() { |
| 275 | + jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; |
| 276 | + eventData = ''; |
| 277 | + eventCnts = {}; |
| 278 | + gd = createGraphDiv(); |
| 279 | + }); |
| 280 | + |
| 281 | + afterEach(destroyGraphDiv); |
| 282 | + |
| 283 | + function _plot(fig) { |
| 284 | + return Plotly.newPlot(gd, fig).then(function() { |
| 285 | + eventNames.forEach(function(k) { |
| 286 | + eventCnts[k] = 0; |
| 287 | + gd.on(k, function(d) { |
| 288 | + eventData = d; |
| 289 | + eventCnts[k]++; |
| 290 | + Lib.clearThrottle(); |
| 291 | + }); |
| 292 | + }); |
| 293 | + }); |
| 294 | + } |
| 295 | + |
| 296 | + function assertEventPointData(expected, msg) { |
| 297 | + var actual = eventData.points || []; |
| 298 | + |
| 299 | + expect(actual.length) |
| 300 | + .toBe(expected.length, msg + ' same number of pts'); |
| 301 | + |
| 302 | + expected.forEach(function(e, i) { |
| 303 | + var a = actual[i]; |
| 304 | + var m = msg + ' (pt ' + i + ')'; |
| 305 | + |
| 306 | + for(var k in e) { |
| 307 | + expect(a[k]).toBeCloseTo(e[k], 1, m + ' ' + k); |
| 308 | + } |
| 309 | + }); |
| 310 | + } |
| 311 | + |
| 312 | + function assertEventCnt(expected, msg) { |
| 313 | + eventNames.forEach(function(k) { |
| 314 | + var m = msg + ' event cnt for ' + k; |
| 315 | + |
| 316 | + if(k in expected) { |
| 317 | + expect(eventCnts[k]).toBe(expected[k], m); |
| 318 | + } else { |
| 319 | + expect(eventCnts[k]).toBe(0, m); |
| 320 | + } |
| 321 | + }); |
| 322 | + } |
| 323 | + |
| 324 | + function _hover(pos) { |
| 325 | + eventData = ''; |
| 326 | + mouseEvent('mousemove', pos[0], pos[1]); |
| 327 | + } |
| 328 | + |
| 329 | + function _unhover(pos) { |
| 330 | + eventData = ''; |
| 331 | + mouseEvent('mouseout', pos[0], pos[1]); |
| 332 | + } |
| 333 | + |
| 334 | + it('should trigger hover/unhover/click/doubleclick events', function(done) { |
| 335 | + var fig = Lib.extendDeep({}, require('@mocks/zzz_smith_axes.json')); |
| 336 | + var ptPos = [159, 138]; |
| 337 | + var blankPos = [109, 109]; |
| 338 | + var marginPos = [20, 20]; |
| 339 | + |
| 340 | + function _assert(ptExpectation, cntExpecation, msg) { |
| 341 | + if(Array.isArray(ptExpectation)) { |
| 342 | + assertEventPointData(ptExpectation, msg); |
| 343 | + } else { |
| 344 | + expect(eventData).toBe(ptExpectation, msg); |
| 345 | + } |
| 346 | + assertEventCnt(cntExpecation, msg); |
| 347 | + } |
| 348 | + |
| 349 | + _plot(fig) |
| 350 | + .then(function() { _hover(ptPos); }) |
| 351 | + .then(function() { |
| 352 | + _assert([{ |
| 353 | + re: 0.5, |
| 354 | + im: 0.5 |
| 355 | + }], { |
| 356 | + plotly_hover: 1 |
| 357 | + }, 'after hover on pt'); |
| 358 | + }) |
| 359 | + .then(function() { _unhover(blankPos);}) |
| 360 | + .then(function() { |
| 361 | + _assert([{ |
| 362 | + re: 0.5, |
| 363 | + im: 0.5 |
| 364 | + }], { |
| 365 | + plotly_hover: 1, |
| 366 | + plotly_unhover: 1 |
| 367 | + }, 'after unhover off pt'); |
| 368 | + }) |
| 369 | + .then(function() { _hover(marginPos);}) |
| 370 | + .then(function() { |
| 371 | + _assert('', { |
| 372 | + plotly_hover: 1, |
| 373 | + plotly_unhover: 1, |
| 374 | + }, 'after hovering in margin'); |
| 375 | + }) |
| 376 | + .then(done, done.fail); |
| 377 | + }); |
46 | 378 | });
|
0 commit comments