OLD | NEW |
1 var localStorage; | 1 var localStorage; |
2 var document; | 2 var document; |
3 var window; | 3 var window; |
| 4 var XMLHttpRequest; |
| 5 var lastCreatedXhr; |
4 | 6 |
5 function testGetSetValue() { | 7 function testGetSetValue() { |
6 localStorage = new LocalStorageFake(); | 8 localStorage = new LocalStorageFake(); |
7 GM_setValue('string', 'value'); | 9 GM_setValue('string', 'value'); |
8 assert('value', GM_getValue('string')); | 10 assert('value', GM_getValue('string')); |
9 GM_setValue('integer', 123); | 11 GM_setValue('integer', 123); |
10 assert(123, GM_getValue('integer')); | 12 assert(123, GM_getValue('integer')); |
11 GM_setValue('boolean', true); | 13 GM_setValue('boolean', true); |
12 assert(true, GM_getValue('boolean')); | 14 assert(true, GM_getValue('boolean')); |
13 | 15 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
58 }); | 60 }); |
59 } | 61 } |
60 | 62 |
61 function testGetResourceText() { | 63 function testGetResourceText() { |
62 assertThrow(function() { | 64 assertThrow(function() { |
63 var resource = GM_getResourceText('textResourceName'); | 65 var resource = GM_getResourceText('textResourceName'); |
64 }); | 66 }); |
65 } | 67 } |
66 | 68 |
67 function testAddStyle() { | 69 function testAddStyle() { |
| 70 var documentElement = new ElementFake(''); |
68 var head = new ElementFake('head'); | 71 var head = new ElementFake('head'); |
69 document = new DocumentFake(head); | 72 document = new DocumentFake(documentElement, head); |
70 var css = 'color: #decaff;'; | 73 var css = 'color: #decaff;'; |
71 GM_addStyle(css); | 74 GM_addStyle(css); |
| 75 assert(0, documentElement.childNodes.length); |
72 assert(1, head.childNodes.length); | 76 assert(1, head.childNodes.length); |
73 var style = head.childNodes[0]; | 77 var style = head.childNodes[0]; |
74 assert("style", style.tagName); | 78 assert("style", style.tagName); |
75 assert("text/css", style.type); | 79 assert("text/css", style.type); |
76 assert(css, style.innerHTML); | 80 assert(1, style.childNodes.length); |
| 81 var textNode = style.childNodes[0]; |
| 82 assert(css, textNode.text); |
| 83 |
| 84 document = new DocumentFake(documentElement, null); |
| 85 GM_addStyle(css); |
| 86 assert(1, documentElement.childNodes.length); |
| 87 var style = documentElement.childNodes[0]; |
| 88 assert("text/css", style.type); |
| 89 assert(1, style.childNodes.length); |
| 90 textNode = style.childNodes[0]; |
| 91 assert(css, textNode.text); |
77 } | 92 } |
78 | 93 |
79 function testXmlhttpRequest() { | 94 function testXmlhttpRequest() { |
80 var xhr = GM_xmlhttpRequest({}); | 95 XMLHttpRequest = XMLHttpRequestFake; |
| 96 var url = 'http://example.com'; |
| 97 |
| 98 var onLoadCallback = function(state) { |
| 99 onLoadCallbackResponseState = state; |
| 100 }; |
| 101 var onErrorCallback = function(state) { |
| 102 onErrorCallbackResponseState = state; |
| 103 }; |
| 104 var onReadyStateChangeCallback = function(state) { |
| 105 onReadyStateChangeCallbackResponseState = state; |
| 106 }; |
| 107 |
| 108 var details = { |
| 109 onload: onLoadCallback, |
| 110 onerror: onErrorCallback, |
| 111 onreadystatechange: onReadyStateChangeCallback, |
| 112 method: 'GET', |
| 113 url: url, |
| 114 overrideMimeType: 'text/html', |
| 115 headers: { |
| 116 'X-Header': 'foo' |
| 117 }, |
| 118 data: 'data' |
| 119 }; |
| 120 |
| 121 GM_xmlhttpRequest(details); |
| 122 var xhr = lastCreatedXhr; |
| 123 |
| 124 assert('GET', xhr.openedMethod); |
| 125 assert(url, xhr.openedUrl); |
| 126 assert('text/html', xhr.overrideMimeType); |
| 127 assert('foo', xhr.requestHeaders['X-Header']); |
| 128 assert('data', xhr.sentBody); |
| 129 |
| 130 xhr.responseText = 'foo'; |
| 131 xhr.responseHeaders['X-Response'] = 'foo'; |
| 132 xhr.status = 200; |
| 133 xhr.statusText = 'OK'; |
| 134 |
| 135 xhr.readyState = 1; |
| 136 xhr.onreadystatechange(); |
| 137 var state = onReadyStateChangeCallbackResponseState; |
| 138 assert(xhr.responseText, state.responseText); |
| 139 assert(xhr.readyState, state.readyState); |
| 140 assert('', state.responseHeaders); |
| 141 assert(0, state.status); |
| 142 assert('', state.statusText); |
| 143 assert('', state.finalUrl); |
| 144 |
| 145 xhr.readyState = 0; |
| 146 xhr.onerror(); |
| 147 state = onErrorCallbackResponseState; |
| 148 assert(xhr.responseText, state.responseText); |
| 149 assert(xhr.readyState, state.readyState); |
| 150 assert('', state.responseHeaders); |
| 151 assert(0, state.status); |
| 152 assert('', state.statusText); |
| 153 assert('', state.finalUrl); |
| 154 |
| 155 xhr.readyState = 4; |
| 156 xhr.onload(); |
| 157 state = onLoadCallbackResponseState; |
| 158 assert(xhr.responseText, state.responseText); |
| 159 assert(xhr.readyState, state.readyState); |
| 160 assert('X-Response: foo\r\n', state.responseHeaders); |
| 161 assert(xhr.status, state.status); |
| 162 assert(xhr.statusText, state.statusText); |
| 163 assert(url, state.finalUrl); |
81 } | 164 } |
82 | 165 |
83 function testRegisterMenuCommand() { | 166 function testRegisterMenuCommand() { |
84 assertThrow(function() { | 167 assertThrow(function() { |
85 GM_registerMenuCommand('name', function() {}, 'a', '', 'a'); | 168 GM_registerMenuCommand('name', function() {}, 'a', '', 'a'); |
86 }); | 169 }); |
87 } | 170 } |
88 | 171 |
89 function testOpenInTab() { | 172 function testOpenInTab() { |
90 var mockWindow = { | 173 var mockWindow = { |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
148 updateKeys_: function() { | 231 updateKeys_: function() { |
149 var keys = []; | 232 var keys = []; |
150 for (var key in this.map_) { | 233 for (var key in this.map_) { |
151 keys.push(key); | 234 keys.push(key); |
152 } | 235 } |
153 this.keys_ = keys; | 236 this.keys_ = keys; |
154 this.length = keys.length; | 237 this.length = keys.length; |
155 } | 238 } |
156 } | 239 } |
157 | 240 |
158 function DocumentFake(head) { | 241 function DocumentFake(documentElement, head) { |
| 242 this.documentElement = documentElement; |
159 this.head_ = head; | 243 this.head_ = head; |
160 } | 244 } |
161 DocumentFake.prototype = { | 245 DocumentFake.prototype = { |
162 getElementsByTagName: function(tagName) { | 246 getElementsByTagName: function(tagName) { |
163 if (tagName == 'head' && this.head_) { | 247 if (tagName == 'head' && this.head_) { |
164 return [this.head_]; | 248 return [this.head_]; |
165 } | 249 } |
166 return []; | 250 return []; |
167 }, | 251 }, |
168 createElement: function(tagName) { | 252 createElement: function(tagName) { |
169 return new ElementFake(tagName); | 253 return new ElementFake(tagName); |
| 254 }, |
| 255 createTextNode: function(text) { |
| 256 return new TextNodeFake(text); |
170 } | 257 } |
171 } | 258 } |
172 | 259 |
173 function ElementFake(tagName) { | 260 function ElementFake(tagName) { |
174 this.tagName = tagName; | 261 this.tagName = tagName; |
| 262 this.childNodes = []; |
175 } | 263 } |
176 ElementFake.prototype = { | 264 ElementFake.prototype = { |
177 childNodes: [], | |
178 appendChild: function(e) { | 265 appendChild: function(e) { |
179 this.childNodes.push(e); | 266 this.childNodes.push(e); |
180 return e; | 267 return e; |
| 268 } |
| 269 } |
| 270 |
| 271 function TextNodeFake(text) { |
| 272 this.text = text; |
| 273 } |
| 274 |
| 275 function XMLHttpRequestFake() { |
| 276 lastCreatedXhr = this; |
| 277 this.onload = null; |
| 278 this.onerror = null; |
| 279 this.onreadystatechange = null; |
| 280 this.openedMethod = null; |
| 281 this.openededUrl = null; |
| 282 this.overriddenMimeType = null; |
| 283 this.requestHeaders = {}; |
| 284 this.sentBody = null; |
| 285 this.responseText = null; |
| 286 this.readyState = null; |
| 287 this.responseHeaders = {}; |
| 288 this.status = null; |
| 289 this.statusText = null; |
| 290 } |
| 291 XMLHttpRequestFake.prototype = { |
| 292 open: function(method, url) { |
| 293 this.openedMethod = method; |
| 294 this.openedUrl = url; |
181 }, | 295 }, |
| 296 overrideMimeType: function(mimeType) { |
| 297 this.overrideMimeType = mimeType; |
| 298 }, |
| 299 setRequestHeader: function(header, value) { |
| 300 this.requestHeaders[header] = value; |
| 301 }, |
| 302 send: function(opt_body) { |
| 303 this.sentBody = opt_body; |
| 304 }, |
| 305 getAllResponseHeaders: function() { |
| 306 var s = ''; |
| 307 for (var header in this.responseHeaders) { |
| 308 // The delimiter used in Webkit's XMLHttpRequest is \r\n, however |
| 309 // the new Chrome networking code (and Firefox) uses \n, so watch |
| 310 // out for this! |
| 311 s += header + ': ' + this.responseHeaders[header] + '\r\n'; |
| 312 } |
| 313 return s; |
| 314 } |
182 } | 315 } |
183 | 316 |
184 function assert(expected, actual) { | 317 function assert(expected, actual) { |
185 if (expected !== actual) { | 318 if (expected !== actual) { |
186 throw new Error('Assert failed: "' + expected + '" !== "' + actual + '"'); | 319 throw new Error('Assert failed: "' + expected + '" !== "' + actual + '"'); |
187 } | |
188 } | |
189 | |
190 function fail() { | |
191 throw new Error('Fail'); | |
192 } | |
193 | |
194 function assertThrow(f) { | |
195 var threw = false; | |
196 try { | |
197 f(); | |
198 } catch(e) { | |
199 threw = true; | |
200 } | |
201 if (!threw) { | |
202 throw new Error('Assert failed, expression did not throw.'); | |
203 } | |
204 } | |
205 var localStorage; | |
206 var document; | |
207 var window; | |
208 | |
209 function testGetSetValue() { | |
210 localStorage = new LocalStorageFake(); | |
211 GM_setValue('string', 'value'); | |
212 assert('value', GM_getValue('string')); | |
213 GM_setValue('integer', 123); | |
214 assert(123, GM_getValue('integer')); | |
215 GM_setValue('boolean', true); | |
216 assert(true, GM_getValue('boolean')); | |
217 | |
218 assert(undefined, GM_getValue('notset')); | |
219 assert('default', GM_getValue('notset', 'default')); | |
220 | |
221 // illegal values | |
222 assertThrow(function() { | |
223 GM_setValue('illegal value', null); | |
224 }); | |
225 assertThrow(function() { | |
226 GM_setValue('illegal value', 1.5); | |
227 }); | |
228 } | |
229 | |
230 function testDeleteValue() { | |
231 localStorage = new LocalStorageFake(); | |
232 GM_setValue('delete', 'value'); | |
233 assert('value', GM_getValue('delete')); | |
234 GM_deleteValue('delete'); | |
235 assert(undefined, GM_getValue('delete')); | |
236 GM_deleteValue('notset'); | |
237 } | |
238 | |
239 function testListValues() { | |
240 localStorage = new LocalStorageFake(); | |
241 var a = GM_listValues(); | |
242 assert(0, a.length); | |
243 | |
244 GM_setValue('one', 'first'); | |
245 a = GM_listValues(); | |
246 assert(1, a.length); | |
247 assert('one', a[0]); | |
248 | |
249 GM_setValue('two', 'second'); | |
250 a = GM_listValues(); | |
251 | |
252 // Test that keys that are not namespaced can't be read. | |
253 localStorage.setItem('three', 'third'); | |
254 assert(2, a.length); | |
255 assert(true, a.indexOf('one') >= 0); | |
256 assert(true, a.indexOf('two') >= 0); | |
257 } | |
258 | |
259 function testGetResourceURL() { | |
260 assertThrow(function() { | |
261 var resource = GM_getResourceURL('urlResourceName'); | |
262 }); | |
263 } | |
264 | |
265 function testGetResourceText() { | |
266 assertThrow(function() { | |
267 var resource = GM_getResourceText('textResourceName'); | |
268 }); | |
269 } | |
270 | |
271 function testAddStyle() { | |
272 var head = new ElementFake('head'); | |
273 document = new DocumentFake(head); | |
274 var css = 'color: #decaff;'; | |
275 GM_addStyle(css); | |
276 assert(1, head.childNodes.length); | |
277 var style = head.childNodes[0]; | |
278 assert("style", style.tagName); | |
279 assert("text/css", style.type); | |
280 assert(css, style.innerHTML); | |
281 } | |
282 | |
283 function testXmlhttpRequest() { | |
284 var xhr = GM_xmlhttpRequest({}); | |
285 } | |
286 | |
287 function testRegisterMenuCommand() { | |
288 assertThrow(function() { | |
289 GM_registerMenuCommand('name', function() {}, 'a', '', 'a'); | |
290 }); | |
291 } | |
292 | |
293 function testOpenInTab() { | |
294 var mockWindow = { | |
295 open: function(url, name, opt_options) { | |
296 this.openedUrl = url; | |
297 this.openedName = name; | |
298 this.openedOptions = opt_options; | |
299 } | |
300 }; | |
301 window = mockWindow; | |
302 var url = 'http://example.com'; | |
303 GM_openInTab(url); | |
304 assert(mockWindow.openedUrl, url); | |
305 } | |
306 | |
307 function testLog() { | |
308 var mockWindow = { | |
309 console: { | |
310 message: null, | |
311 log: function(message) { | |
312 this.message = message; | |
313 } | |
314 } | |
315 }; | |
316 window = mockWindow; | |
317 var message = 'hello world'; | |
318 GM_log(message); | |
319 assert(message, mockWindow.console.message); | |
320 } | |
321 | |
322 function LocalStorageFake() { | |
323 this.map_ = {}; | |
324 this.keys_ = []; | |
325 } | |
326 LocalStorageFake.prototype = { | |
327 length: 0, | |
328 key: function(index) { | |
329 if (index >= this.length) { | |
330 throw new Error('INDEX_SIZE_ERR'); | |
331 } | |
332 return this.keys_[index]; | |
333 }, | |
334 getItem: function(key) { | |
335 if (key in this.map_) { | |
336 return this.map_[key]; | |
337 } | |
338 return null; | |
339 }, | |
340 setItem: function(key, data) { | |
341 this.map_[key] = data; | |
342 this.updateKeys_(); | |
343 }, | |
344 removeItem: function(key) { | |
345 delete this.map_[key]; | |
346 this.updateKeys_(); | |
347 }, | |
348 clear: function() { | |
349 this.map_ = {}; | |
350 this.updateKeys_(); | |
351 }, | |
352 updateKeys_: function() { | |
353 var keys = []; | |
354 for (var key in this.map_) { | |
355 keys.push(key); | |
356 } | |
357 this.keys_ = keys; | |
358 this.length = keys.length; | |
359 } | |
360 } | |
361 | |
362 function DocumentFake(head) { | |
363 this.head_ = head; | |
364 } | |
365 DocumentFake.prototype = { | |
366 getElementsByTagName: function(tagName) { | |
367 if (tagName == 'head' && this.head_) { | |
368 return [this.head_]; | |
369 } | |
370 return []; | |
371 }, | |
372 createElement: function(tagName) { | |
373 return new ElementFake(tagName); | |
374 } | |
375 } | |
376 | |
377 function ElementFake(tagName) { | |
378 this.tagName = tagName; | |
379 } | |
380 ElementFake.prototype = { | |
381 childNodes: [], | |
382 appendChild: function(e) { | |
383 this.childNodes.push(e); | |
384 return e; | |
385 }, | |
386 } | |
387 | |
388 function assert(expected, actual) { | |
389 if (expected !== actual) { | |
390 throw new Error('Assert failed: "' + expected + '" !== "' + actual + '"'); | |
391 } | 320 } |
392 } | 321 } |
393 | 322 |
394 function fail() { | 323 function fail() { |
395 throw new Error('Fail'); | 324 throw new Error('Fail'); |
396 } | 325 } |
397 | 326 |
398 function assertThrow(f) { | 327 function assertThrow(f) { |
399 var threw = false; | 328 var threw = false; |
400 try { | 329 try { |
401 f(); | 330 f(); |
402 } catch(e) { | 331 } catch(e) { |
403 threw = true; | 332 threw = true; |
404 } | 333 } |
405 if (!threw) { | 334 if (!threw) { |
406 throw new Error('Assert failed, expression did not throw.'); | 335 throw new Error('Assert failed, expression did not throw.'); |
407 } | 336 } |
408 } | 337 } |
| 338 |
OLD | NEW |