| 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 |