|
1 | 1 | 'use strict';
|
2 | 2 |
|
3 | 3 | var Plotly = require('@lib/index');
|
4 |
| -var Plots = require('@src/plots/plots'); |
5 | 4 |
|
6 |
| -var createGraphDiv = require('../assets/create_graph_div'); |
7 |
| -var destroyGraphDiv = require('../assets/destroy_graph_div'); |
| 5 | +var withSetupTeardown = require('../assets/with_setup_teardown'); |
8 | 6 | var mouseEvent = require('../assets/mouse_event');
|
9 | 7 |
|
10 |
| -function teardown(gd, done) { |
| 8 | +// Expected shape of projection-related data |
| 9 | +var cameraStructure = { |
| 10 | + up: {x: jasmine.any(Number), y: jasmine.any(Number), z: jasmine.any(Number)}, |
| 11 | + center: {x: jasmine.any(Number), y: jasmine.any(Number), z: jasmine.any(Number)}, |
| 12 | + eye: {x: jasmine.any(Number), y: jasmine.any(Number), z: jasmine.any(Number)} |
| 13 | +}; |
11 | 14 |
|
12 |
| - // The teardown function needs information of what to tear down so afterEach can not be used without global vars. |
13 |
| - // In addition to removing the plot from the DOM it also destroy possibly present 2D or 3D scenes |
14 |
| - |
15 |
| - // TODO we should figure out something to only rely on public API calls |
16 |
| - // In other words, how can users themselves properly destroy the plot through the API? |
17 |
| - // This function is left in this file until the above todo is looked into. |
18 |
| - var fullLayout = gd._fullLayout; |
19 |
| - |
20 |
| - Plots.getSubplotIds(fullLayout, 'gl3d').forEach(function(sceneId) { |
21 |
| - var scene = fullLayout[sceneId]._scene; |
22 |
| - if(scene.glplot) scene.destroy(); |
23 |
| - }); |
24 |
| - |
25 |
| - Plots.getSubplotIds(fullLayout, 'gl2d').forEach(function(sceneId) { |
26 |
| - var scene2d = fullLayout._plots[sceneId]._scene2d; |
27 |
| - if(scene2d.glplot) { |
28 |
| - scene2d.stopped = true; |
29 |
| - scene2d.destroy(); |
30 |
| - } |
31 |
| - }); |
32 |
| - |
33 |
| - destroyGraphDiv(); |
34 |
| - |
35 |
| - // A test case can only be called 'done' when the above destroy methods had been performed. |
36 |
| - // One way of helping ensure that the destroys are not forgotten is that done() is part of |
37 |
| - // the teardown, consequently if a test case omits the teardown by accident, the test will |
38 |
| - // visibly hang. If the teardown receives no proper arguments, it'll also visibly fail. |
39 |
| - done(); |
| 15 | +function makePlot(gd, mock) { |
| 16 | + return Plotly.plot(gd, mock.data, mock.layout); |
40 | 17 | }
|
41 | 18 |
|
42 |
| -describe('Test gl plot interactions', function() { |
43 |
| - |
44 |
| - describe('gl3d plots', function() { |
45 |
| - |
46 |
| - // Expected shape of projection-related data |
47 |
| - var cameraStructure = { |
48 |
| - up: {x: jasmine.any(Number), y: jasmine.any(Number), z: jasmine.any(Number)}, |
49 |
| - center: {x: jasmine.any(Number), y: jasmine.any(Number), z: jasmine.any(Number)}, |
50 |
| - eye: {x: jasmine.any(Number), y: jasmine.any(Number), z: jasmine.any(Number)} |
51 |
| - }; |
52 |
| - |
53 |
| - function makePlot(mock) { |
54 |
| - return Plotly.plot(createGraphDiv(), mock.data, mock.layout); |
55 |
| - } |
| 19 | +function addEventCallback(graphDiv) { |
| 20 | + var relayoutCallback = jasmine.createSpy('relayoutCallback'); |
| 21 | + graphDiv.on('plotly_relayout', relayoutCallback); |
| 22 | + return {graphDiv: graphDiv, relayoutCallback: relayoutCallback}; |
| 23 | +} |
56 | 24 |
|
57 |
| - function addEventCallback(graphDiv) { |
58 |
| - var relayoutCallback = jasmine.createSpy('relayoutCallback'); |
59 |
| - graphDiv.on('plotly_relayout', relayoutCallback); |
60 |
| - return {graphDiv: graphDiv, relayoutCallback: relayoutCallback}; |
61 |
| - } |
| 25 | +function verifyInteractionEffects(tuple) { |
62 | 26 |
|
63 |
| - function verifyInteractionEffects(tuple) { |
| 27 | + // One 'drag': simulating fairly thoroughly as the mouseup event is also needed here |
| 28 | + mouseEvent('mousemove', 400, 200); |
| 29 | + mouseEvent('mousedown', 400, 200); |
| 30 | + mouseEvent('mousemove', 320, 320, {buttons: 1}); |
| 31 | + mouseEvent('mouseup', 320, 320); |
64 | 32 |
|
65 |
| - // One 'drag': simulating fairly thoroughly as the mouseup event is also needed here |
66 |
| - mouseEvent('mousemove', 400, 200); |
67 |
| - mouseEvent('mousedown', 400, 200); |
68 |
| - mouseEvent('mousemove', 320, 320, {buttons: 1}); |
69 |
| - mouseEvent('mouseup', 320, 320); |
| 33 | + // Check event emission count |
| 34 | + expect(tuple.relayoutCallback).toHaveBeenCalledTimes(1); |
70 | 35 |
|
71 |
| - // Check event emission count |
72 |
| - expect(tuple.relayoutCallback).toHaveBeenCalledTimes(1); |
| 36 | + // Check structure of event callback value contents |
| 37 | + expect(tuple.relayoutCallback).toHaveBeenCalledWith(jasmine.objectContaining({scene: cameraStructure})); |
73 | 38 |
|
74 |
| - // Check structure of event callback value contents |
75 |
| - expect(tuple.relayoutCallback).toHaveBeenCalledWith(jasmine.objectContaining({scene: cameraStructure})); |
| 39 | + // Check camera contents on the DIV layout |
| 40 | + var divCamera = tuple.graphDiv.layout.scene.camera; |
76 | 41 |
|
77 |
| - // Check camera contents on the DIV layout |
78 |
| - var divCamera = tuple.graphDiv.layout.scene.camera; |
| 42 | + expect(divCamera).toEqual(cameraStructure); |
79 | 43 |
|
80 |
| - expect(divCamera).toEqual(cameraStructure); |
| 44 | + return tuple.graphDiv; |
| 45 | +} |
81 | 46 |
|
82 |
| - return tuple.graphDiv; |
83 |
| - } |
| 47 | +function testEvents(plot) { |
| 48 | + return plot |
| 49 | + .then(function(graphDiv) { |
| 50 | + var tuple = addEventCallback(graphDiv); // TODO disuse tuple with ES6 |
| 51 | + verifyInteractionEffects(tuple); |
| 52 | + }); |
| 53 | +} |
84 | 54 |
|
85 |
| - function testEvents(plot, done) { |
86 |
| - plot.then(function(graphDiv) { |
87 |
| - var tuple = addEventCallback(graphDiv); // TODO disuse tuple with ES6 |
88 |
| - verifyInteractionEffects(tuple); |
89 |
| - teardown(graphDiv, done); |
90 |
| - }); |
91 |
| - } |
| 55 | +describe('gl3d plots', function() { |
92 | 56 |
|
93 |
| - it('should respond to drag interactions with mock of unset camera', function(done) { |
94 |
| - testEvents(makePlot(require('@mocks/gl3d_scatter3d-connectgaps.json')), done); |
| 57 | + it('should respond to drag interactions with mock of unset camera', function(done) { |
| 58 | + withSetupTeardown(done, function(gd) { |
| 59 | + return testEvents(makePlot(gd, require('@mocks/gl3d_scatter3d-connectgaps.json'))); |
95 | 60 | });
|
| 61 | + }); |
96 | 62 |
|
97 |
| - it('should respond to drag interactions with mock of partially set camera', function(done) { |
98 |
| - testEvents(makePlot(require('@mocks/gl3d_errorbars_zx.json')), done); |
| 63 | + it('should respond to drag interactions with mock of partially set camera', function(done) { |
| 64 | + withSetupTeardown(done, function(gd) { |
| 65 | + return testEvents(makePlot(gd, require('@mocks/gl3d_errorbars_zx.json'))); |
99 | 66 | });
|
100 | 67 | });
|
101 | 68 | });
|
0 commit comments