{"action":"created","comment":{"url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/pulls/comments/46838319","id":46838319,"diff_hunk":"@@ -0,0 +1,424 @@\n+var StorageWrapper = hammerhead.get('./sandbox/storages/wrapper');\r\n+var settings       = hammerhead.get('./settings');\r\n+\r\n+var storageSandbox = hammerhead.sandbox.storageSandbox;\r\n+var iframeSandbox  = hammerhead.sandbox.iframe;\r\n+var Promise        = hammerhead.Promise;\r\n+var isIE           = hammerhead.utils.browser.isIE;\r\n+\r\n+var storageWrapperKey = 'hammerhead|storage-wrapper|' + settings.get().sessionId + '|example.com';\r\n+\r\n+QUnit.testStart(function () {\r\n+    // NOTE: Clean up storage wrappers\r\n+    window.localStorage.clear();\r\n+    window.sessionStorage.clear();\r\n+    storageSandbox.localStorage.clear();\r\n+    storageSandbox.sessionStorage.clear();\r\n+\r\n+    iframeSandbox.on(iframeSandbox.IFRAME_READY_TO_INIT_EVENT, initIframeTestHandler);\r\n+    iframeSandbox.off(iframeSandbox.IFRAME_READY_TO_INIT_EVENT, iframeSandbox.iframeReadyToInitHandler);\r\n+});\r\n+\r\n+QUnit.testDone(function () {\r\n+    iframeSandbox.off(iframeSandbox.IFRAME_READY_TO_INIT_EVENT, initIframeTestHandler);\r\n+});\r\n+\r\n+function waitStorageUpdated () {\r\n+    return new Promise(function (resolve) {\r\n+        window.setTimeout(resolve, 100);\r\n+    });\r\n+}\r\n+\r\n+function waitIframeLoad (iframe) {\r\n+    return new Promise(function (resolve) {\r\n+        $(iframe).load(resolve);\r\n+    });\r\n+}\r\n+\r\n+function waitStorageEvent (window, action) {\r\n+    return new Promise(function (resolve) {\r\n+        var handler = function (e) {\r\n+            window.removeEventListener('storage', handler);\r\n+            resolve(e);\r\n+        };\r\n+\r\n+        window.addEventListener('storage', handler);\r\n+        action();\r\n+    });\r\n+}\r\n+\r\n+module('Storage API');\r\n+\r\n+test('Argument types', function () {\r\n+    var storageWrapper = storageSandbox.localStorage;\r\n+\r\n+    storageWrapper.setItem({}, 'value');\r\n+    strictEqual(storageWrapper.getItem({}), 'value');\r\n+\r\n+    storageWrapper.setItem({}, null);\r\n+    strictEqual(storageWrapper.getItem({}), 'null');\r\n+\r\n+    storageWrapper.setItem(null, 'value1');\r\n+    strictEqual(storageWrapper.getItem(null), 'value1');\r\n+});\r\n+\r\n+test('Get item', function () {\r\n+    var storageWrapper = storageSandbox.sessionStorage;\r\n+\r\n+    storageWrapper.setItem('key1', 'value1');\r\n+    storageWrapper.setItem('key2', 'value2');\r\n+\r\n+    strictEqual(storageWrapper.getItem('key1'), 'value1');\r\n+    strictEqual(storageWrapper.getItem('key2'), 'value2');\r\n+    strictEqual(storageWrapper.getItem('key3'), null);\r\n+});\r\n+\r\n+test('Set item', function () {\r\n+    var storageWrapper = storageSandbox.localStorage;\r\n+\r\n+    storageWrapper.setItem('key1', 'value1');\r\n+    storageWrapper.setItem('key2', {});\r\n+\r\n+    strictEqual(storageWrapper.length, 2);\r\n+    strictEqual(storageWrapper.getItem('key1'), 'value1');\r\n+    strictEqual(storageWrapper.getItem('key2'), '[object Object]');\r\n+\r\n+    storageWrapper.setItem('key1', null);\r\n+    storageWrapper.setItem('key2', 'newValue');\r\n+\r\n+    strictEqual(storageWrapper.length, 2);\r\n+    strictEqual(storageWrapper.getItem('key1'), 'null');\r\n+    strictEqual(storageWrapper.getItem('key2'), 'newValue');\r\n+});\r\n+\r\n+test('Get key', function () {\r\n+    var storageWrapper = storageSandbox.sessionStorage;\r\n+\r\n+    storageWrapper.setItem('key1', 'value1');\r\n+    storageWrapper.setItem('key2', 'value2');\r\n+\r\n+    strictEqual(storageWrapper.length, 2);\r\n+    strictEqual(storageWrapper.key(-1), null);\r\n+    strictEqual(storageWrapper.key(0), 'key1');\r\n+    strictEqual(storageWrapper.key(1), 'key2');\r\n+    strictEqual(storageWrapper.key(2), null);\r\n+});\r\n+\r\n+test('Remove item', function () {\r\n+    var storageWrapper = storageSandbox.localStorage;\r\n+\r\n+    storageWrapper.setItem('key1', 'value1');\r\n+    storageWrapper.setItem('key2', 'value2');\r\n+\r\n+    storageWrapper.removeItem('key3');\r\n+    strictEqual(storageWrapper.length, 2);\r\n+    storageWrapper.removeItem('key1');\r\n+    strictEqual(storageWrapper.length, 1);\r\n+    strictEqual(storageWrapper.getItem('key1'), null);\r\n+    strictEqual(storageWrapper.getItem('key2'), 'value2');\r\n+    strictEqual(storageWrapper.key(0), 'key2');\r\n+    strictEqual(storageWrapper.key(1), null);\r\n+});\r\n+\r\n+test('Storage length', function () {\r\n+    var storageWrapper = storageSandbox.sessionStorage;\r\n+\r\n+    storageWrapper.clear();\r\n+    strictEqual(storageWrapper.length, 0);\r\n+\r\n+    storageWrapper.setItem('key1', 'value1');\r\n+    strictEqual(storageWrapper.length, 1);\r\n+\r\n+    storageWrapper.setItem('key2', 'value2');\r\n+    strictEqual(storageWrapper.length, 2);\r\n+\r\n+    storageWrapper.removeItem('key2');\r\n+    strictEqual(storageWrapper.length, 1);\r\n+\r\n+    storageWrapper.clear();\r\n+    strictEqual(storageWrapper.length, 0);\r\n+});\r\n+\r\n+module('Code instrumentation');\r\n+\r\n+test('Global invoke', function () {\r\n+    var localStorageWrapper   = storageSandbox.localStorage;\r\n+    var sessionStorageWrapper = storageSandbox.sessionStorage;\r\n+\r\n+    eval(processScript('localStorage.key1 = \"value1\"'));\r\n+    eval(processScript('sessionStorage.key2 = \"value2\"'));\r\n+\r\n+    strictEqual(localStorageWrapper.key1, 'value1');\r\n+    strictEqual(sessionStorageWrapper.key2, 'value2');\r\n+\r\n+    localStorageWrapper.setItem('key3', 'value3');\r\n+    sessionStorageWrapper.setItem('key4', 'value4');\r\n+\r\n+    strictEqual(eval(processScript('localStorage.key3')), 'value3');\r\n+    strictEqual(eval(processScript('sessionStorage.key4')), 'value4');\r\n+\r\n+    eval(processScript('localStorage.setItem(\"key5\", \"value5\")'));\r\n+    eval(processScript('sessionStorage.setItem(\"key6\", \"value6\")'));\r\n+\r\n+    strictEqual(localStorageWrapper.key5, 'value5');\r\n+    strictEqual(sessionStorageWrapper.key6, 'value6');\r\n+\r\n+    eval(processScript('window.localStorage.setItem(\"key7\", \"value7\")'));\r\n+    eval(processScript('window.sessionStorage.setItem(\"key8\", \"value8\")'));\r\n+\r\n+    strictEqual(localStorageWrapper.key7, 'value7');\r\n+    strictEqual(sessionStorageWrapper.key8, 'value8');\r\n+\r\n+    eval(processScript('window[\"localStorage\"].setItem(\"key9\", \"value9\")'));\r\n+    eval(processScript('window[\"sessionStorage\"].setItem(\"key10\", \"value10\")'));\r\n+\r\n+    strictEqual(localStorageWrapper.key9, 'value9');\r\n+    strictEqual(sessionStorageWrapper.key10, 'value10');\r\n+\r\n+    eval(processScript('localStorage[\"setItem\"](\"key11\", \"value11\")'));\r\n+    eval(processScript('sessionStorage[\"setItem\"](\"key12\", \"value12\")'));\r\n+\r\n+    strictEqual(localStorageWrapper.key11, 'value11');\r\n+    strictEqual(sessionStorageWrapper.key12, 'value12');\r\n+\r\n+    eval(processScript('localStorage[\"key13\"] = \"value13\"'));\r\n+    eval(processScript('sessionStorage[\"key14\"] = \"value14\"'));\r\n+\r\n+    strictEqual(localStorageWrapper.key13, 'value13');\r\n+    strictEqual(sessionStorageWrapper.key14, 'value14');\r\n+\r\n+    eval(processScript('var key = \"key15\"; localStorage[key] = \"value15\"'));\r\n+    eval(processScript('var key = \"key16\"; sessionStorage[key] = \"value16\"'));\r\n+\r\n+    strictEqual(localStorageWrapper.key15, 'value15');\r\n+    strictEqual(sessionStorageWrapper.key16, 'value16');\r\n+});\r\n+\r\n+test('Invoke as a member', function () {\r\n+    var localStorageWrapper   = storageSandbox.localStorage;\r\n+    var sessionStorageWrapper = storageSandbox.sessionStorage;\r\n+\r\n+    strictEqual(eval(processScript('window.localStorage')), localStorageWrapper);\r\n+    strictEqual(eval(processScript('window.sessionStorage')), sessionStorageWrapper);\r\n+\r\n+    strictEqual(eval(processScript('window[\"localStorage\"]')), localStorageWrapper);\r\n+    strictEqual(eval(processScript('window[\"sessionStorage\"]')), sessionStorageWrapper);\r\n+\r\n+    /* eslint-disable no-unused-vars */\r\n+    var localStorageLiteral   = 'localStorage';\r\n+    var sessionStorageLiteral = 'sessionStorage';\r\n+    /* eslint-enable no-unused-vars */\r\n+\r\n+    strictEqual(eval(processScript('window[localStorageLiteral]')), localStorageWrapper);\r\n+    strictEqual(eval(processScript('window[sessionStorageLiteral]')), sessionStorageWrapper);\r\n+});\r\n+\r\n+module('Direct record to the storage');\r\n+\r\n+test('Setter', function () {\r\n+    var storageWrapper = storageSandbox.sessionStorage;\r\n+\r\n+    storageWrapper.key1 = 'value1';\r\n+    strictEqual(storageWrapper.getItem('key1'), 'value1');\r\n+    strictEqual(storageWrapper.length, 1);\r\n+\r\n+    storageWrapper.key1 = 'newValue';\r\n+    strictEqual(storageWrapper.getItem('key1'), 'newValue');\r\n+    strictEqual(storageWrapper.length, 1);\r\n+});\r\n+\r\n+test('Getter', function () {\r\n+    var storageWrapper = storageSandbox.localStorage;\r\n+\r\n+    storageWrapper.setItem('key1', 'value1');\r\n+    strictEqual(storageWrapper.key1, 'value1');\r\n+\r\n+    storageWrapper.setItem('key1', null);\r\n+    strictEqual(storageWrapper.key1, 'null');\r\n+\r\n+    storageWrapper.setItem(null, null);\r\n+    strictEqual(storageWrapper.null, 'null');\r\n+\r\n+    storageWrapper.removeItem(null);\r\n+    strictEqual(storageWrapper.null, void 0);\r\n+});\r\n+\r\n+module('Area of visibility');\r\n+\r\n+asyncTest('Iframe with empty src', function () {\r\n+    var topStorage = storageSandbox.localStorage;\r\n+    var iframe     = document.createElement('iframe');\r\n+\r\n+    iframe.id       = 'test001';\r\n+    topStorage.key1 = 'value1';\r\n+\r\n+    waitIframeLoad(iframe)\r\n+        .then(function () {\r\n+            var iframeStorage = iframe.contentWindow['%hammerhead%'].sandbox.storageSandbox.localStorage;\r\n+\r\n+            strictEqual(iframeStorage.key1, 'value1');\r\n+\r\n+            iframeStorage.key2 = 'value2';\r\n+            topStorage.key3    = 'value3';\r\n+\r\n+            strictEqual(topStorage.key2, 'value2');\r\n+            strictEqual(iframeStorage.key3, 'value3');\r\n+\r\n+            $(iframe).remove();\r\n+            start();\r\n+        });\r\n+\r\n+    document.body.appendChild(iframe);\r\n+});\r\n+\r\n+module('Sync state with native');\r\n+\r\n+test('Storages load they state from native', function () {\r\n+    localStorage[storageWrapperKey]   = '[[ \"key1\" ],[ \"value1\" ]]';\r\n+    sessionStorage[storageWrapperKey] = '[[ \"key2\" ],[ \"value2\" ]]';\r\n+\r\n+    var localSandboxWrapper   = new StorageWrapper(window, localStorage, storageWrapperKey, hammerhead.sandbox.event.listeners);\r\n+    var sessionSandboxWrapper = new StorageWrapper(window, sessionStorage, storageWrapperKey, hammerhead.sandbox.event.listeners);\r\n+\r\n+    strictEqual(localSandboxWrapper.key1, 'value1');\r\n+    strictEqual(sessionSandboxWrapper.key2, 'value2');\r\n+});\r\n+\r\n+test('Storages save they state on beforeunload event', function () {\r\n+    storageSandbox.localStorage.key1   = 'value1';\r\n+    storageSandbox.sessionStorage.key2 = 'value2';\r\n+\r\n+    ok(!localStorage[storageWrapperKey]);\r\n+    ok(!sessionStorage[storageWrapperKey]);\r\n+\r\n+    // NOTE: Simulate page leaving\r\n+    hammerhead.sandbox.event.unload._emitBeforeUnloadEvent();\r\n+\r\n+    strictEqual(localStorage[storageWrapperKey], JSON.stringify([['key1'], ['value1']]));\r\n+    strictEqual(sessionStorage[storageWrapperKey], JSON.stringify([['key2'], ['value2']]));\r\n+});\r\n+\r\n+module('Storage changed event');\r\n+\r\n+asyncTest('Event firing in all same host windows', function () {\r\n+    var topStorage    = storageSandbox.localStorage;\r\n+    var iframeStorage = null;\r\n+    var iframe        = document.createElement('iframe');\r\n+\r\n+    var topStorageEventArgs    = [];\r\n+    var iframeStorageEventArgs = [];\r\n+\r\n+    var topWindowHandler = function (e) {\r\n+        topStorageEventArgs.push(e);\r\n+    };\r\n+\r\n+    var iframeWindowHandler = function (e) {\r\n+        iframeStorageEventArgs.push(e);\r\n+    };\r\n+\r\n+    iframe.id = 'test001';\r\n+\r\n+    waitIframeLoad(iframe)\r\n+        .then(function () {\r\n+            iframeStorage = iframe.contentWindow['%hammerhead%'].sandbox.storageSandbox.localStorage;\r\n+\r\n+            window.addEventListener('storage', topWindowHandler);\r\n+            iframe.contentWindow.addEventListener('storage', iframeWindowHandler);\r\n+\r\n+            iframeStorage.key1 = 'value1';\r\n+\r\n+            return waitStorageUpdated();\r\n+        })\r\n+        .then(function () {\r\n+            strictEqual(topStorageEventArgs.length, 1);\r\n+            strictEqual(iframeStorageEventArgs.length, 1);\r\n+\r\n+            strictEqual(topStorageEventArgs[0].key, 'key1');\r\n+            strictEqual(topStorageEventArgs[0].oldValue, isIE ? '' : null);\r\n+            strictEqual(topStorageEventArgs[0].newValue, 'value1');\r\n+            // NOTE: we can't detect who change the storage\r","path":"test/client/fixtures/sandbox/storages-test.js","position":339,"original_position":339,"commit_id":"f88539b40f9aafd959f8c7f3464109706a818b0a","original_commit_id":"f88539b40f9aafd959f8c7f3464109706a818b0a","user":{"login":"VasilyStrelyaev","id":11459924,"avatar_url":"https://avatars.githubusercontent.com/u/11459924?v=3","gravatar_id":"","url":"https://api.github.com/users/VasilyStrelyaev","html_url":"https://github.com/VasilyStrelyaev","followers_url":"https://api.github.com/users/VasilyStrelyaev/followers","following_url":"https://api.github.com/users/VasilyStrelyaev/following{/other_user}","gists_url":"https://api.github.com/users/VasilyStrelyaev/gists{/gist_id}","starred_url":"https://api.github.com/users/VasilyStrelyaev/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/VasilyStrelyaev/subscriptions","organizations_url":"https://api.github.com/users/VasilyStrelyaev/orgs","repos_url":"https://api.github.com/users/VasilyStrelyaev/repos","events_url":"https://api.github.com/users/VasilyStrelyaev/events{/privacy}","received_events_url":"https://api.github.com/users/VasilyStrelyaev/received_events","type":"User","site_admin":false},"body":"```\r\n            // NOTE: we can't detect who changed the storage\r\n```","created_at":"2015-12-07T16:06:00Z","updated_at":"2015-12-07T16:06:00Z","html_url":"https://github.com/DevExpress/testcafe-hammerhead/pull/300#discussion_r46838319","pull_request_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/pulls/300","_links":{"self":{"href":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/pulls/comments/46838319"},"html":{"href":"https://github.com/DevExpress/testcafe-hammerhead/pull/300#discussion_r46838319"},"pull_request":{"href":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/pulls/300"}}},"pull_request":{"url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/pulls/300","id":52003199,"html_url":"https://github.com/DevExpress/testcafe-hammerhead/pull/300","diff_url":"https://github.com/DevExpress/testcafe-hammerhead/pull/300.diff","patch_url":"https://github.com/DevExpress/testcafe-hammerhead/pull/300.patch","issue_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/issues/300","number":300,"state":"open","locked":false,"title":"Add localStorage/sessionStorage sandbox (close #252)","user":{"login":"churkin","id":5182202,"avatar_url":"https://avatars.githubusercontent.com/u/5182202?v=3","gravatar_id":"","url":"https://api.github.com/users/churkin","html_url":"https://github.com/churkin","followers_url":"https://api.github.com/users/churkin/followers","following_url":"https://api.github.com/users/churkin/following{/other_user}","gists_url":"https://api.github.com/users/churkin/gists{/gist_id}","starred_url":"https://api.github.com/users/churkin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/churkin/subscriptions","organizations_url":"https://api.github.com/users/churkin/orgs","repos_url":"https://api.github.com/users/churkin/repos","events_url":"https://api.github.com/users/churkin/events{/privacy}","received_events_url":"https://api.github.com/users/churkin/received_events","type":"User","site_admin":false},"body":"Guys, it is not finish pull request, i just want to make sure that this approach is suitable for all browsers.","created_at":"2015-11-27T15:03:16Z","updated_at":"2015-12-07T16:06:00Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ed75d1445ea4bb6b86369945304a661f7eb4fabe","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/pulls/300/commits","review_comments_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/pulls/300/comments","review_comment_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/pulls/comments{/number}","comments_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/issues/300/comments","statuses_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/statuses/f88539b40f9aafd959f8c7f3464109706a818b0a","head":{"label":"churkin:storages","ref":"storages","sha":"f88539b40f9aafd959f8c7f3464109706a818b0a","user":{"login":"churkin","id":5182202,"avatar_url":"https://avatars.githubusercontent.com/u/5182202?v=3","gravatar_id":"","url":"https://api.github.com/users/churkin","html_url":"https://github.com/churkin","followers_url":"https://api.github.com/users/churkin/followers","following_url":"https://api.github.com/users/churkin/following{/other_user}","gists_url":"https://api.github.com/users/churkin/gists{/gist_id}","starred_url":"https://api.github.com/users/churkin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/churkin/subscriptions","organizations_url":"https://api.github.com/users/churkin/orgs","repos_url":"https://api.github.com/users/churkin/repos","events_url":"https://api.github.com/users/churkin/events{/privacy}","received_events_url":"https://api.github.com/users/churkin/received_events","type":"User","site_admin":false},"repo":{"id":39562496,"name":"testcafe-hammerhead","full_name":"churkin/testcafe-hammerhead","owner":{"login":"churkin","id":5182202,"avatar_url":"https://avatars.githubusercontent.com/u/5182202?v=3","gravatar_id":"","url":"https://api.github.com/users/churkin","html_url":"https://github.com/churkin","followers_url":"https://api.github.com/users/churkin/followers","following_url":"https://api.github.com/users/churkin/following{/other_user}","gists_url":"https://api.github.com/users/churkin/gists{/gist_id}","starred_url":"https://api.github.com/users/churkin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/churkin/subscriptions","organizations_url":"https://api.github.com/users/churkin/orgs","repos_url":"https://api.github.com/users/churkin/repos","events_url":"https://api.github.com/users/churkin/events{/privacy}","received_events_url":"https://api.github.com/users/churkin/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/churkin/testcafe-hammerhead","description":"","fork":true,"url":"https://api.github.com/repos/churkin/testcafe-hammerhead","forks_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/forks","keys_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/keys{/key_id}","collaborators_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/teams","hooks_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/hooks","issue_events_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/issues/events{/number}","events_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/events","assignees_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/assignees{/user}","branches_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/branches{/branch}","tags_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/tags","blobs_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/git/refs{/sha}","trees_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/git/trees{/sha}","statuses_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/statuses/{sha}","languages_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/languages","stargazers_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/stargazers","contributors_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/contributors","subscribers_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/subscribers","subscription_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/subscription","commits_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/commits{/sha}","git_commits_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/git/commits{/sha}","comments_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/comments{/number}","issue_comment_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/issues/comments{/number}","contents_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/contents/{+path}","compare_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/compare/{base}...{head}","merges_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/merges","archive_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/downloads","issues_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/issues{/number}","pulls_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/pulls{/number}","milestones_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/milestones{/number}","notifications_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/labels{/name}","releases_url":"https://api.github.com/repos/churkin/testcafe-hammerhead/releases{/id}","created_at":"2015-07-23T11:03:55Z","updated_at":"2015-07-24T11:26:01Z","pushed_at":"2015-12-07T13:34:51Z","git_url":"git://github.com/churkin/testcafe-hammerhead.git","ssh_url":"git@github.com:churkin/testcafe-hammerhead.git","clone_url":"https://github.com/churkin/testcafe-hammerhead.git","svn_url":"https://github.com/churkin/testcafe-hammerhead","homepage":null,"size":1860,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"DevExpress:master","ref":"master","sha":"4dd43621c10ac6bfcea44a656970c4b254e5f6de","user":{"login":"DevExpress","id":4243232,"avatar_url":"https://avatars.githubusercontent.com/u/4243232?v=3","gravatar_id":"","url":"https://api.github.com/users/DevExpress","html_url":"https://github.com/DevExpress","followers_url":"https://api.github.com/users/DevExpress/followers","following_url":"https://api.github.com/users/DevExpress/following{/other_user}","gists_url":"https://api.github.com/users/DevExpress/gists{/gist_id}","starred_url":"https://api.github.com/users/DevExpress/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DevExpress/subscriptions","organizations_url":"https://api.github.com/users/DevExpress/orgs","repos_url":"https://api.github.com/users/DevExpress/repos","events_url":"https://api.github.com/users/DevExpress/events{/privacy}","received_events_url":"https://api.github.com/users/DevExpress/received_events","type":"Organization","site_admin":false},"repo":{"id":36883823,"name":"testcafe-hammerhead","full_name":"DevExpress/testcafe-hammerhead","owner":{"login":"DevExpress","id":4243232,"avatar_url":"https://avatars.githubusercontent.com/u/4243232?v=3","gravatar_id":"","url":"https://api.github.com/users/DevExpress","html_url":"https://github.com/DevExpress","followers_url":"https://api.github.com/users/DevExpress/followers","following_url":"https://api.github.com/users/DevExpress/following{/other_user}","gists_url":"https://api.github.com/users/DevExpress/gists{/gist_id}","starred_url":"https://api.github.com/users/DevExpress/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/DevExpress/subscriptions","organizations_url":"https://api.github.com/users/DevExpress/orgs","repos_url":"https://api.github.com/users/DevExpress/repos","events_url":"https://api.github.com/users/DevExpress/events{/privacy}","received_events_url":"https://api.github.com/users/DevExpress/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/DevExpress/testcafe-hammerhead","description":"A powerful web-proxy used as a core for the TestCafe testing framework.","fork":false,"url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead","forks_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/forks","keys_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/keys{/key_id}","collaborators_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/teams","hooks_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/hooks","issue_events_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/issues/events{/number}","events_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/events","assignees_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/assignees{/user}","branches_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/branches{/branch}","tags_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/tags","blobs_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/git/refs{/sha}","trees_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/git/trees{/sha}","statuses_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/statuses/{sha}","languages_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/languages","stargazers_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/stargazers","contributors_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/contributors","subscribers_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/subscribers","subscription_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/subscription","commits_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/commits{/sha}","git_commits_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/git/commits{/sha}","comments_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/comments{/number}","issue_comment_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/issues/comments{/number}","contents_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/contents/{+path}","compare_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/compare/{base}...{head}","merges_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/merges","archive_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/downloads","issues_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/issues{/number}","pulls_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/pulls{/number}","milestones_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/milestones{/number}","notifications_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/labels{/name}","releases_url":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/releases{/id}","created_at":"2015-06-04T16:56:53Z","updated_at":"2015-11-19T10:59:06Z","pushed_at":"2015-12-07T15:52:31Z","git_url":"git://github.com/DevExpress/testcafe-hammerhead.git","ssh_url":"git@github.com:DevExpress/testcafe-hammerhead.git","clone_url":"https://github.com/DevExpress/testcafe-hammerhead.git","svn_url":"https://github.com/DevExpress/testcafe-hammerhead","homepage":"","size":1548,"stargazers_count":5,"watchers_count":5,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":9,"mirror_url":null,"open_issues_count":30,"forks":9,"open_issues":30,"watchers":5,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/pulls/300"},"html":{"href":"https://github.com/DevExpress/testcafe-hammerhead/pull/300"},"issue":{"href":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/issues/300"},"comments":{"href":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/issues/300/comments"},"review_comments":{"href":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/pulls/300/comments"},"review_comment":{"href":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/pulls/300/commits"},"statuses":{"href":"https://api.github.com/repos/DevExpress/testcafe-hammerhead/statuses/f88539b40f9aafd959f8c7f3464109706a818b0a"}}}}