|
1 | 1 | var Plotly = require('@lib/index');
|
2 | 2 |
|
| 3 | +var cssModule = require('@src/lib/plotcss_utils'); |
| 4 | +var plotcss = require('@build/plotcss'); |
| 5 | + |
3 | 6 | var createGraphDiv = require('../assets/create_graph_div');
|
4 | 7 | var destroyGraphDiv = require('../assets/destroy_graph_div');
|
5 | 8 |
|
6 | 9 | describe('css injection', function() {
|
7 |
| - var plotcss_utils = require('@src/lib/plotcss_utils'); |
8 |
| - var plotcss = require('@build/plotcss'); |
9 |
| - |
10 |
| - // create a graph div in a child window |
11 |
| - function createGraphDivInChildWindow() { |
12 |
| - var childWindow = window.open('about:blank', 'popoutWindow', ''); |
13 |
| - |
14 |
| - var gd = childWindow.document.createElement('div'); |
15 |
| - gd.id = 'graph'; |
16 |
| - childWindow.document.body.appendChild(gd); |
17 | 10 |
|
18 |
| - // force the graph to be at position 0,0 no matter what |
19 |
| - gd.style.position = 'fixed'; |
20 |
| - gd.style.left = 0; |
21 |
| - gd.style.top = 0; |
22 |
| - |
23 |
| - return gd; |
24 |
| - } |
25 |
| - |
26 |
| - // the most basic of basic plots |
27 | 11 | function plot(target) {
|
28 | 12 | return Plotly.plot(target, [{
|
29 | 13 | x: [1, 2, 3, 4, 5],
|
30 |
| - y: [1, 2, 4, 8, 16] |
| 14 | + y: [1, 2, 4, 8, 16], |
31 | 15 | }], {
|
32 |
| - margin: { |
33 |
| - t: 0 |
34 |
| - } |
| 16 | + margin: { t: 0 } |
35 | 17 | });
|
36 | 18 | }
|
37 | 19 |
|
38 |
| - // deletes all rules defined in plotcss |
39 |
| - function deletePlotCSSRules(sourceDocument) { |
40 |
| - for(var selector in plotcss) { |
41 |
| - var fullSelector = plotcss_utils.buildFullSelector(selector); |
42 |
| - |
43 |
| - for(var i = 0; i < sourceDocument.styleSheets.length; i++) { |
44 |
| - var styleSheet = sourceDocument.styleSheets[i]; |
45 |
| - var selectors = []; |
46 |
| - |
47 |
| - for(var j = 0; j < styleSheet.cssRules.length; j++) { |
48 |
| - var cssRule = styleSheet.cssRules[j]; |
49 |
| - |
50 |
| - selectors.push(cssRule.selectorText); |
51 |
| - } |
| 20 | + function loopOverRules(_document, assertion) { |
| 21 | + var allSelectors = getAllRuleSelectors(_document); |
52 | 22 |
|
53 |
| - var selectorIndex = selectors.indexOf(fullSelector); |
| 23 | + for(var selector in plotcss) { |
| 24 | + var fullSelector = cssModule.buildFullSelector(selector), |
| 25 | + firstIndex = allSelectors.indexOf(fullSelector); |
54 | 26 |
|
55 |
| - if(selectorIndex !== -1) { |
56 |
| - styleSheet.deleteRule(selectorIndex); |
57 |
| - break; |
58 |
| - } |
59 |
| - } |
| 27 | + assertion(allSelectors, fullSelector, firstIndex); |
60 | 28 | }
|
61 | 29 | }
|
62 | 30 |
|
63 |
| - it('inserts styles on initial plot', function(done) { |
64 |
| - deletePlotCSSRules(document); // clear the rules |
65 |
| - |
66 |
| - // fix scope errors |
67 |
| - var selector = null; |
68 |
| - var fullSelector = null; |
| 31 | + function assertClearence(allSelectors, fullSelector) { |
| 32 | + expect(allSelectors.indexOf(fullSelector)).toEqual(-1); |
| 33 | + } |
69 | 34 |
|
70 |
| - // make sure the rules are cleared |
71 |
| - var allSelectors = plotcss_utils.getAllRuleSelectors(document); |
| 35 | + function assertPresence(allSelectors, fullSelector) { |
| 36 | + expect(allSelectors.indexOf(fullSelector)).not.toEqual(-1); |
| 37 | + } |
72 | 38 |
|
73 |
| - for(selector in plotcss) { |
74 |
| - fullSelector = plotcss_utils.buildFullSelector(selector); |
| 39 | + function assertUniqueness(allSelectors, fullSelector, firstIndex) { |
| 40 | + expect(allSelectors.indexOf(fullSelector, firstIndex + 1)).toEqual(-1); |
| 41 | + } |
75 | 42 |
|
76 |
| - expect(allSelectors.indexOf(fullSelector)).toEqual(-1); |
77 |
| - } |
| 43 | + it('inserts styles on initial plot', function(done) { |
| 44 | + loopOverRules(document, assertClearence); |
78 | 45 |
|
79 |
| - // plot |
80 | 46 | var gd = createGraphDiv();
|
81 |
| - plot(gd).then(function() { |
82 |
| - |
83 |
| - // check for styles |
84 |
| - allSelectors = plotcss_utils.getAllRuleSelectors(document); |
85 | 47 |
|
86 |
| - for(selector in plotcss) { |
87 |
| - fullSelector = plotcss_utils.buildFullSelector(selector); |
88 |
| - |
89 |
| - expect(allSelectors.indexOf(fullSelector)).not.toEqual(-1); |
90 |
| - } |
| 48 | + plot(gd).then(function() { |
| 49 | + expect(gd._document).toBe(window.document); |
| 50 | + loopOverRules(gd._document, assertPresence); |
91 | 51 |
|
92 |
| - // clean up |
93 |
| - return destroyGraphDiv(); |
94 |
| - }).then(done); |
| 52 | + deletePlotCSSRules(gd._document); |
| 53 | + destroyGraphDiv(); |
| 54 | + done(); |
| 55 | + }); |
95 | 56 | });
|
96 | 57 |
|
97 | 58 | it('inserts styles in a child window document', function(done) {
|
98 |
| - var gd = createGraphDivInChildWindow(); |
99 |
| - var childWindow = gd.ownerDocument.defaultView; |
| 59 | + loopOverRules(document, assertClearence); |
| 60 | + |
| 61 | + var childWindow = window.open('about:blank', 'popoutWindow', ''); |
| 62 | + var gd = createGraphDiv(childWindow.document); |
100 | 63 |
|
101 |
| - // plot |
102 | 64 | plot(gd).then(function() {
|
| 65 | + expect(gd._document).toBe(childWindow.document); |
| 66 | + loopOverRules(gd._document, assertPresence); |
103 | 67 |
|
104 |
| - // check for styles |
105 |
| - var allSelectors = plotcss_utils.getAllRuleSelectors(gd.ownerDocument); |
| 68 | + deletePlotCSSRules(gd._document); |
| 69 | + childWindow.document.body.removeChild(gd); |
| 70 | + childWindow.close(); |
| 71 | + done(); |
| 72 | + }); |
| 73 | + }); |
106 | 74 |
|
107 |
| - for(var selector in plotcss) { |
108 |
| - var fullSelector = plotcss_utils.buildFullSelector(selector); |
| 75 | + it('does not insert duplicate styles', function(done) { |
| 76 | + loopOverRules(document, assertClearence); |
109 | 77 |
|
110 |
| - expect(allSelectors.indexOf(fullSelector)).not.toEqual(-1); |
111 |
| - } |
| 78 | + var gd = createGraphDiv(); |
112 | 79 |
|
113 |
| - // clean up |
114 |
| - childWindow.close(); |
115 |
| - }).then(done); |
| 80 | + plot(gd).then(function() { |
| 81 | + |
| 82 | + // plot again so injectStyles gets called again |
| 83 | + return plot(gd); |
| 84 | + }).then(function() { |
| 85 | + expect(gd._document).toBe(window.document); |
| 86 | + loopOverRules(gd._document, assertUniqueness); |
| 87 | + |
| 88 | + deletePlotCSSRules(gd._document); |
| 89 | + destroyGraphDiv(); |
| 90 | + done(); |
| 91 | + }); |
116 | 92 | });
|
| 93 | +}); |
117 | 94 |
|
118 |
| - it('does not insert duplicate styles', function(done) { |
119 |
| - deletePlotCSSRules(document); // clear the rules |
| 95 | +// Gets all the rules currently attached to the document |
| 96 | +// inspired by http://stackoverflow.com/a/23613052/4068492 |
| 97 | +function getAllRuleSelectors(_document) { |
| 98 | + var allSelectors = []; |
120 | 99 |
|
121 |
| - // fix scope errors |
122 |
| - var selector = null; |
123 |
| - var fullSelector = null; |
| 100 | + for(var i = 0; i < _document.styleSheets.length; i++) { |
| 101 | + var styleSheet = _document.styleSheets[i]; |
124 | 102 |
|
125 |
| - // make sure the rules are cleared |
126 |
| - var allSelectors = plotcss_utils.getAllRuleSelectors(document); |
| 103 | + try { |
| 104 | + if(!styleSheet.cssRules) continue; |
| 105 | + } |
| 106 | + catch(e) { |
| 107 | + if(e.name !== 'SecurityError') throw e; |
| 108 | + continue; |
| 109 | + } |
127 | 110 |
|
128 |
| - for(selector in plotcss) { |
129 |
| - fullSelector = plotcss_utils.buildFullSelector(selector); |
| 111 | + for(var j = 0; j < styleSheet.cssRules.length; j++) { |
| 112 | + var cssRule = styleSheet.cssRules[j]; |
130 | 113 |
|
131 |
| - expect(allSelectors.indexOf(fullSelector)).toEqual(-1); |
| 114 | + allSelectors.push(cssRule.selectorText); |
132 | 115 | }
|
| 116 | + } |
133 | 117 |
|
134 |
| - // plot |
135 |
| - var gd = createGraphDiv(); |
136 |
| - plot(gd).then(function() { |
137 |
| - return plot(gd); // plot again so injectStyles gets called again |
138 |
| - }).then(function() { |
139 |
| - // check for styles |
140 |
| - allSelectors = plotcss_utils.getAllRuleSelectors(document); |
| 118 | + return allSelectors; |
| 119 | +} |
141 | 120 |
|
142 |
| - for(selector in plotcss) { |
143 |
| - fullSelector = plotcss_utils.buildFullSelector(selector); |
| 121 | +// Deletes all rules defined in plotcss |
| 122 | +// inspired by http://stackoverflow.com/a/23613052/4068492 |
| 123 | +function deletePlotCSSRules(_document) { |
| 124 | + for(var selector in plotcss) { |
| 125 | + var fullSelector = cssModule.buildFullSelector(selector); |
144 | 126 |
|
145 |
| - var firstIndex = allSelectors.indexOf(fullSelector); |
| 127 | + for(var i = 0; i < _document.styleSheets.length; i++) { |
| 128 | + var styleSheet = _document.styleSheets[i]; |
| 129 | + var selectors = []; |
146 | 130 |
|
147 |
| - // there should be no occurences after the initial one |
148 |
| - expect(allSelectors.indexOf(fullSelector, firstIndex + 1)).toEqual(-1); |
| 131 | + try { |
| 132 | + if(!styleSheet.cssRules) continue; |
| 133 | + } |
| 134 | + catch(e) { |
| 135 | + if(e.name !== 'SecurityError') throw e; |
| 136 | + continue; |
149 | 137 | }
|
150 | 138 |
|
151 |
| - // clean up |
152 |
| - return destroyGraphDiv(); |
153 |
| - }).then(done); |
154 |
| - }); |
155 |
| -}); |
| 139 | + for(var j = 0; j < styleSheet.cssRules.length; j++) { |
| 140 | + var cssRule = styleSheet.cssRules[j]; |
| 141 | + |
| 142 | + selectors.push(cssRule.selectorText); |
| 143 | + } |
| 144 | + |
| 145 | + var selectorIndex = selectors.indexOf(fullSelector); |
| 146 | + |
| 147 | + if(selectorIndex !== -1) { |
| 148 | + styleSheet.deleteRule(selectorIndex); |
| 149 | + break; |
| 150 | + } |
| 151 | + } |
| 152 | + } |
| 153 | +} |
0 commit comments