{"action":"created","comment":{"url":"https://api.github.com/repos/Shopify/turbograft/pulls/comments/75947370","id":75947370,"diff_hunk":"@@ -1,210 +1,946 @@\n describe 'Turbolinks', ->\n-\n-  createTurboNodule = ->\n-    $nodule = $(\"<div>\").attr(\"id\", \"turbo-area\").attr(\"refresh\", \"turbo-area\")\n-    return $nodule[0]\n-\n-  url_for = (slug) ->\n+  server = null\n+  pushStateStub = null\n+  replaceStateStub = null\n+\n+  ROUTE_TEMPLATE_INDEX = 2\n+\n+  TURBO_EVENTS = [\n+    'page:change',\n+    'page:update',\n+    'page:load',\n+    'page:before-change',\n+    'page:before-partial-replace',\n+    'page:after-change',\n+    'page:after-node-removed',\n+    'page:fetch',\n+    'page:receive',\n+    'page:after-script-inserted',\n+    'page:after-link-inserted',\n+    'page:after-link-removed'\n+  ]\n+\n+  ROUTES = {\n+    noScriptsOrLinkInHead: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div>YOLO</div>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\">Hi bob</div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    singleScriptInHead: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <script src='#{ASSET_FIXTURES['foo.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"foo\"\n+              type=\"text/javascript\"></script>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    twoScriptsInHead: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <script src='#{ASSET_FIXTURES['foo.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"foo\"\n+              type=\"text/javascript\"></script>\n+            <script src='#{ASSET_FIXTURES['bar.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"bar\"\n+              type=\"text/javascript\"></script>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    differentSingleScriptInHead: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <script src='#{ASSET_FIXTURES['bar.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"bar\"\n+              type=\"text/javascript\"></script>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    singleScriptInHeadWithDifferentSourceButSameName: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <script src='#{ASSET_FIXTURES['bar.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"foo\"\n+              type=\"text/javascript\"></script>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    secondLibraryOnly: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <script src='#{ASSET_FIXTURES['b.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"b\"\n+              type=\"text/javascript\"></script>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    threeScriptsInHeadABC: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <script src='#{ASSET_FIXTURES['a.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"a\"\n+              type=\"text/javascript\"></script>\n+            <script src='#{ASSET_FIXTURES['b.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"b\"\n+              type=\"text/javascript\"></script>\n+            <script src='#{ASSET_FIXTURES['c.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"c\"\n+              type=\"text/javascript\"></script>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    threeScriptsInHeadACB: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <script src='#{ASSET_FIXTURES['a.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"a\"\n+              type=\"text/javascript\"></script>\n+            <script src='#{ASSET_FIXTURES['c.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"c\"\n+              type=\"text/javascript\"></script>\n+            <script src='#{ASSET_FIXTURES['b.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"b\"\n+              type=\"text/javascript\"></script>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    threeScriptsInHeadBAC: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <script src='#{ASSET_FIXTURES['b.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"b\"\n+              type=\"text/javascript\"></script>\n+            <script src='#{ASSET_FIXTURES['a.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"a\"\n+              type=\"text/javascript\"></script>\n+            <script src='#{ASSET_FIXTURES['c.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"c\"\n+              type=\"text/javascript\"></script>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    threeScriptsInHeadBCA: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <script src='#{ASSET_FIXTURES['b.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"b\"\n+              type=\"text/javascript\"></script>\n+            <script src='#{ASSET_FIXTURES['c.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"c\"\n+              type=\"text/javascript\"></script>\n+            <script src='#{ASSET_FIXTURES['a.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"a\"\n+              type=\"text/javascript\"></script>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    threeScriptsInHeadCAB: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <script src='#{ASSET_FIXTURES['c.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"c\"\n+              type=\"text/javascript\"></script>\n+            <script src='#{ASSET_FIXTURES['a.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"a\"\n+              type=\"text/javascript\"></script>\n+            <script src='#{ASSET_FIXTURES['b.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"b\"\n+              type=\"text/javascript\"></script>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    threeScriptsInHeadCBA: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <script src='#{ASSET_FIXTURES['c.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"c\"\n+              type=\"text/javascript\"></script>\n+            <script src='#{ASSET_FIXTURES['b.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"b\"\n+              type=\"text/javascript\"></script>\n+            <script src='#{ASSET_FIXTURES['a.js']}'\n+              data-turbolinks-track=\"true\"\n+              data-turbolinks-track-script-as=\"a\"\n+              type=\"text/javascript\"></script>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    singleLinkInHead: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <link href='#{ASSET_FIXTURES['foo.css']}' data-turbolinks-track=\"true\"></link>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    twoLinksInHead: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <link href='#{ASSET_FIXTURES['foo.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['bar.css']}' data-turbolinks-track=\"true\"></link>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    twoLinksInHeadReverseOrder: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <link href='#{ASSET_FIXTURES['bar.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['foo.css']}' data-turbolinks-track=\"true\"></link>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    fourLinksInHeadABCD: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <link href='#{ASSET_FIXTURES['a.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['b.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['c.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['d.css']}' data-turbolinks-track=\"true\"></link>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    fourLinksInHeadBCDA: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <link href='#{ASSET_FIXTURES['b.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['c.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['d.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['a.css']}' data-turbolinks-track=\"true\"></link>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    fourLinksInHeadCDAB: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <link href='#{ASSET_FIXTURES['c.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['d.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['a.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['b.css']}' data-turbolinks-track=\"true\"></link>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    fourLinksInHeadCDBA: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <link href='#{ASSET_FIXTURES['c.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['d.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['b.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['a.css']}' data-turbolinks-track=\"true\"></link>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    fourLinksInHeadCBDA: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <link href='#{ASSET_FIXTURES['c.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['b.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['d.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['a.css']}' data-turbolinks-track=\"true\"></link>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    fourLinksInHeadDCBA: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <link href='#{ASSET_FIXTURES['d.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['c.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['b.css']}' data-turbolinks-track=\"true\"></link>\n+            <link href='#{ASSET_FIXTURES['a.css']}' data-turbolinks-track=\"true\"></link>\n+            <title>Hi there!</title>\n+          </head>\n+          <body>\n+            <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    inlineScriptInBody: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <title>Hi</title>\n+          </head>\n+          <body>\n+            <script id=\"turbo-area\" refresh=\"turbo-area\">globalStub()</script>\n+          </body>\n+        </html>\n+        \"\"\"\n+    ],\n+\n+    inlineScriptInBodyTurbolinksEvalFalse: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <title>Hi</title>\n+          </head>\n+          <body>\n+            <script data-turbolinks-eval=\"false\" id=\"turbo-area\" refresh=\"turbo-area\">globalStub()</script>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ],\n+\n+    responseWithRefreshAlways: [\n+      200,\n+      {'Content-Type':'text/html'},\n+      \"\"\"\n+        <!doctype html>\n+        <html>\n+          <head>\n+            <title>Hi</title>\n+          </head>\n+          <body>\n+            <div id=\"div1\" refresh=\"div1\">\n+              <div id=\"div2\" refresh-always>Refresh-always</div>\n+            </div>\n+          </body>\n+        </html>\n+      \"\"\"\n+    ]\n+  }\n+\n+  hasScript = (filename) ->\n+    queryForScript(filename).length > 0\n+\n+  hasLink = (filename) ->\n+    queryForLink(filename).length > 0\n+\n+  hasScriptOnce = (filename) ->\n+    queryForScript(filename).length == 1\n+\n+  hasLinkOnce = (filename) ->\n+    queryForLink(filename).length == 1\n+\n+  queryForLink = (filename) ->\n+    document.querySelectorAll(\"link[href=\\\"#{ASSET_FIXTURES[filename]}\\\"]\")\n+\n+  queryForScript = (filename) ->\n+    document.querySelectorAll(\"script[src=\\\"#{ASSET_FIXTURES[filename]}\\\"]\")\n+\n+  linkOrderPosition = (filename) ->\n+    linksInHead = [].slice.call(document.head.children).filter (node) ->\n+      node.nodeName == 'LINK'\n+    linksInHead.indexOf(queryForLink(filename)[0])\n+\n+  resetPage = ->\n+    document.head.innerHTML = \"\"\n+    document.body.innerHTML = \"\"\"\n+      <div id=\"turbo-area\" refresh=\"turbo-area\"></div>\n+    \"\"\"\n+\n+  urlFor = (slug) ->\n     window.location.origin + slug\n \n+  visit = ({options, url}, callback) ->\n+    $(document).one('page:load', (event) ->\n+      setTimeout((-> callback(event)), 0)\n+    )\n+    Turbolinks.visit('/' + url, options)\n+\n   beforeEach ->\n-    @server = sinon.fakeServer.create()\n+    pushStateStub = stub(Turbolinks, 'pushState')\n+    replaceStateStub = stub(Turbolinks, 'replaceState')\n+    stub(Turbolinks, 'fullPageNavigate', -> $(document).trigger('page:load'))\n+\n+    server = sinon.fakeServer.create()\n+    Object.keys(ROUTES).forEach (url) ->\n+      server.respondWith('/' + url, ROUTES[url])\n+    server.autoRespond = true\n+\n     $(\"script\").attr(\"data-turbolinks-eval\", false)\n     $(\"#mocha\").attr(\"refresh-never\", true)\n-    @replaceStateStub = stub(Turbolinks, \"replaceState\")\n-    @pushStateStub = stub(Turbolinks, \"pushState\")\n-    document.body.appendChild(createTurboNodule())\n+\n+    resetPage()\n \n   afterEach ->\n-    @server.restore()\n-    @pushStateStub.restore()\n-    @replaceStateStub.restore()\n-    $(\"#turbo-area\").remove()\n+    Turbolinks.fullPageNavigate.restore()\n+    Turbolinks.pushState.restore()\n+    Turbolinks.replaceState.restore()\n \n-  html_one = \"\"\"\n-    <!doctype html>\n-    <html>\n-      <head>\n-        <title>Hi there!</title>\n-      </head>\n-      <body>\n-        <div>YOLO</div>\n-        <div id=\"turbo-area\" refresh=\"turbo-area\">Hi bob</div>\n-      </body>\n-    </html>\n-  \"\"\"\n-\n-  script_response = \"\"\"\n-    <!doctype html>\n-    <html>\n-      <head>\n-        <title>Hi</title>\n-      </head>\n-      <body>\n-        <script id=\"turbo-area\" refresh=\"turbo-area\">globalStub()</script>\n-      </body>\n-    </html>\n-  \"\"\"\n-\n-  script_response_turbolinks_eval_false = \"\"\"\n-    <!doctype html>\n-    <html>\n-      <head>\n-        <title>Hi</title>\n-      </head>\n-      <body>\n-        <script data-turbolinks-eval=\"false\" id=\"turbo-area\" refresh=\"turbo-area\">globalStub()</script>\n-      </body>\n-    </html>\n-  \"\"\"\n-\n-  response_with_refresh_always = \"\"\"\n-    <!doctype html>\n-    <html>\n-      <head>\n-        <title>Hi</title>\n-      </head>\n-      <body>\n-        <div id=\"div1\" refresh=\"div1\">\n-          <div id=\"div2\" refresh-always>Refresh-always</div>\n-        </div>\n-      </body>\n-    </html>\n-  \"\"\"\n+    $(document).off(TURBO_EVENTS.join(' '))\n+    $(\"#turbo-area\").remove()\n+    server.restore()\n \n   it 'is defined', ->\n-    assert Turbolinks\n+    assert(Turbolinks)\n \n   describe '#visit', ->\n-    it 'returns if pageChangePrevented', ->\n-      listener = (event) ->\n+    it 'only loads once if called multiple times before an XHR finishes', (done) ->\n+      pageReceive = stub()\n+      $(document).on('page:receive', pageReceive)\n+      visit url: 'noScriptsOrLinkInHead', -> true\n+      visit url: 'noScriptsOrLinkInHead', ->\n+        assert(pageReceive.calledOnce, 'page:receive should only be emitted once!')\n+        done()\n+\n+    it 'returns if pageChangePrevented', (done) ->\n+      $(document).one 'page:before-change', (event) ->\n         event.preventDefault()\n-        assert.equal '/some_request', event.data\n-\n-      window.addEventListener('page:before-change', listener)\n-\n-      Turbolinks.visit \"/some_request\", {partialReplace: true, onlyKeys: ['turbo-area']}\n-      assert.equal 0, @server.requests.length\n-\n-      window.removeEventListener('page:before-change', listener)\n-\n-    it 'supports passing request headers', ->\n-      @server.respondWith([200, { \"Content-Type\": \"text/html\" }, \"<html>Hello World</html>\"]);\n-\n-      Turbolinks.visit \"/some_request\", {headers: {'foo': 'bar', 'fizz': 'buzz'}}\n-      @server.respond()\n-\n-      assert.equal 1, @server.requests.length\n-      assert.equal 'bar', @server.requests[0].requestHeaders['foo']\n-      assert.equal 'buzz', @server.requests[0].requestHeaders['fizz']\n-\n-    describe 'with partial page replacement', ->\n-      it 'uses just the part of the response body we supply', ->\n-        @server.respondWith([200, { \"Content-Type\": \"text/html\" }, html_one]);\n-\n-        Turbolinks.visit \"/some_request\", {partialReplace: true, onlyKeys: ['turbo-area']}\n-        @server.respond()\n-\n-        assert.equal \"Hi there!\", document.title\n-        assert.equal -1, document.body.textContent.indexOf(\"YOLO\")\n-        assert document.body.textContent.indexOf(\"Hi bob\") > 0\n-        assert @pushStateStub.calledOnce\n-        assert @pushStateStub.calledWith({turbolinks: true, url: url_for(\"/some_request\")}, \"\", url_for(\"/some_request\"))\n-        assert.equal 0, @replaceStateStub.callCount\n-\n-      it 'doesn\\'t update the window state if updatePushState is false', ->\n-        @server.respondWith([200, { \"Content-Type\": \"text/html\" }, html_one]);\n-\n-        Turbolinks.visit \"/some_request\", {partialReplace: true, onlyKeys: ['turbo-area'], updatePushState: false}\n-        @server.respond()\n-\n-        assert.equal \"Hi there!\", document.title\n-        assert.equal -1, document.body.textContent.indexOf(\"YOLO\")\n-        assert document.body.textContent.indexOf(\"Hi bob\") > 0\n-        assert @pushStateStub.notCalled\n-        assert @replaceStateStub.notCalled\n-\n-      it 'calls a user-supplied callback', ->\n-        @server.respondWith([200, { \"Content-Type\": \"text/html\" }, html_one]);\n-\n-        your_callback = stub()\n-        Turbolinks.visit \"/some_request\", {partialReplace: true, onlyKeys: ['turbo-area'], callback: your_callback}\n-        @server.respond()\n-\n-        assert your_callback.calledOnce\n-\n-      it 'script tags are evaluated when they are the subject of a partial replace', ->\n-        window.globalStub = stub()\n-        @server.respondWith([200, { \"Content-Type\": \"text/html\" }, script_response]);\n-\n-        Turbolinks.visit \"/some_request\", {partialReplace: true, onlyKeys: ['turbo-area']}\n-        @server.respond()\n-        assert globalStub.calledOnce\n-\n-      it 'script tags are not evaluated if they have [data-turbolinks-eval=\"false\"]', ->\n-        window.globalStub = stub()\n-        @server.respondWith([200, { \"Content-Type\": \"text/html\" }, script_response_turbolinks_eval_false]);\n-\n-        Turbolinks.visit \"/some_request\", {partialReplace: true, onlyKeys: ['turbo-area']}\n-        @server.respond()\n-        assert.equal 0, globalStub.callCount\n-\n-      it 'triggers the page:load event with a list of nodes that are new (freshly replaced)', ->\n-        $(document).one 'page:load', (event) ->\n-          ev = event.originalEvent\n-          assert.equal true, ev.data instanceof Array\n-          assert.equal 1, ev.data.length\n-          node = ev.data[0]\n-\n-          assert.equal \"turbo-area\", node.id\n-          assert.equal \"turbo-area\", node.getAttribute('refresh')\n-\n-        @server.respondWith([200, { \"Content-Type\": \"text/html\" }, html_one]);\n-\n-        Turbolinks.visit \"/some_request\", {partialReplace: true, onlyKeys: ['turbo-area']}\n-        @server.respond()\n-\n-        $(document).off 'page:load'\n-\n-      it 'does not trigger the page:before-partial-replace event more than once', ->\n-        handler = stub()\n-        $(document).on 'page:before-partial-replace', ->\n-          handler()\n-          assert handler.calledOnce\n-\n-        @server.respondWith([200, { \"Content-Type\": \"text/html\" }, html_one]);\n-\n-        Turbolinks.visit \"/some_request\", {partialReplace: true, onlyKeys: ['turbo-area']}\n-        @server.respond()\n-\n-        $(document).off 'page:before-partial-replace'\n-\n-      it 'replaces and passes through the outermost nodes if a series of nodes got replaced', ->\n-        currentBody = \"\"\"\n-          <div id=\"div1\" refresh=\"div1\">\n-            <div id=\"div2\" refresh-always>Refresh-always</div>\n-          </div>\n-        \"\"\"\n-\n-        $(\"body\").append($(currentBody))\n-\n+        assert.equal('/noScriptsOrLinkInHead', event.originalEvent.data)\n+        assert.equal(0, server.requests.length)\n+        done()\n+\n+      visit(url: 'noScriptsOrLinkInHead', options: { partialReplace: true, onlyKeys: ['turbo-area'] })\n+\n+    it 'supports passing request headers', (done) ->\n+      visit url: 'noScriptsOrLinkInHead', options: { headers: {'foo': 'bar', 'fizz': 'buzz'} }, ->\n+        assert.equal('bar', server.requests[0].requestHeaders['foo'])\n+        assert.equal('buzz', server.requests[0].requestHeaders['fizz'])\n+        done()\n+\n+    it 'calls a user-supplied callback', (done) ->\n+      yourCallback = stub()\n+      visit url: 'noScriptsOrLinkInHead', options: {callback: yourCallback}, ->\n+        assert(yourCallback.calledOnce, 'Callback was not called.')\n+        done()\n+\n+  describe 'head link tag tracking', ->\n+    it 'dispatches page:after-link-inserted event when inserting a link on navigation', (done) ->\n+      linkTagInserted = sinon.spy()\n+      $(document).on 'page:after-link-inserted', linkTagInserted\n+\n+      visit url: 'noScriptsOrLinkInHead', ->\n+        visit url: 'singleLinkInHead', ->\n+          assert.equal(linkTagInserted.callCount, 1)\n+          done()\n+\n+    it 'dispatches page:after-link-removed event when removing a link on navigation', (done) ->\n+      linkTagRemoved = sinon.spy()\n+      $(document).on 'page:after-link-removed', linkTagRemoved\n+\n+      visit url: 'singleLinkInHead', ->\n+        visit url: 'noScriptsOrLinkInHead', ->\n+          assert.equal(linkTagRemoved.callCount, 1)\n+          done()\n+\n+    it 'inserts link with a new href into empty head on navigation', (done) ->\n+      visit url: 'noScriptsOrLinkInHead', ->\n+        visit url: 'singleLinkInHead', ->\n+          assert(hasLinkOnce('foo.css'), 'Should insert foo.css tag only once.')\n+          done()\n+\n+    it 'inserts link with a new href into existing head on navigation', (done) ->\n+      visit url: 'singleLinkInHead', ->\n+        visit url: 'twoLinksInHead', ->\n+          assert(hasLinkOnce('bar.css'), 'Should insert bar.css tag only once.')\n+          done()\n+\n+    it 'inserts link with a new href before exiting scripts in head on navigation', (done) ->\n+      visit url: 'singleLinkInHead', ->\n+        visit url: 'twoLinksInHeadReverseOrder', ->\n+          assert(hasLinkOnce('bar.css'), 'Should insert bar.css tag only once.')\n+          done()\n+\n+    it 'does not reinsert link with existing href into identical head on navigation', (done) ->\n+      visit url: 'singleLinkInHead', ->\n+        visit url: 'singleLinkInHead', ->\n+          assert(hasLinkOnce('foo.css'), 'Should insert foo.css tag only once.')\n+          done()\n+\n+    it 'does not reinsert link with existing href into existing head on navigation', (done) ->\n+      visit url: 'singleLinkInHead', ->\n+        visit url: 'twoLinksInHead', ->\n+          assert(hasLinkOnce('foo.css'), 'Should insert foo.css tag only once.')\n+          done()\n+\n+    it 'removes link when navigating to a page with an empty head', (done) ->\n+      visit url: 'singleLinkInHead', ->\n+        visit url: 'noScriptsOrLinkInHead', ->\n+          assert(!hasLink('foo.css'), 'Should remove foo.css tag.')\n+          done()\n+\n+    it 'removes link when navigating to a page with the href missing', (done) ->\n+      visit url: 'twoLinksInHead', ->\n+        visit url: 'singleLinkInHead', ->\n+          assert(!hasLink('bar.css'), 'Should remove bar.css tag.')\n+          done()\n+\n+    describe 'transforms the current head to have the same links in the same order as the upstream document with minimal moves', ->\n+      it 'maintains order when moving from an empty head to a page with link tags.', (done) ->\n+        linkTagInserted = sinon.spy()\n+        $(document).on 'page:after-link-inserted', linkTagInserted\n+        visit url: 'fourLinksInHeadABCD', ->\n+          expectedLinkOrder = ['a.css', 'b.css', 'c.css', 'd.css']\n+          expectedLinkOrder.forEach (link, index) ->\n+            assert.equal(index, linkOrderPosition(link), link + ' should be in position ' + index)\n+          assert.equal(linkTagInserted.callCount, 4)\n+          done()\n+\n+      it 'maintains order when moving from a head with links ABCD to links BCDA.', (done) ->\n+        visit url: 'fourLinksInHeadABCD', ->\n+          linkTagInserted = sinon.spy()\n+          $(document).on 'page:after-link-inserted', linkTagInserted\n+          visit url: 'fourLinksInHeadBCDA', ->\n+            expectedLinkOrder = ['b.css', 'c.css', 'd.css', 'a.css']\n+            expectedLinkOrder.forEach (link, index) ->\n+              assert.equal(index, linkOrderPosition(link), link + ' should be in position ' + index)\n+            assert.equal(linkTagInserted.callCount, 1) # Move A\n+            done()\n+\n+      it 'maintains order when moving from a head with links ABCD to links CDAB.', (done) ->\n+        visit url: 'fourLinksInHeadABCD', ->\n+          linkTagInserted = sinon.spy()\n+          $(document).on 'page:after-link-inserted', linkTagInserted\n+          visit url: 'fourLinksInHeadCDAB', ->\n+            expectedLinkOrder = ['c.css', 'd.css', 'a.css', 'b.css']\n+            expectedLinkOrder.forEach (link, index) ->\n+              assert.equal(index, linkOrderPosition(link), link + ' should be in position ' + index)\n+            assert.equal(linkTagInserted.callCount, 2) # Move A,B or C,D\n+            done()\n+\n+      it 'maintains order when moving from a head with links ABCD to links CDBA.', (done) ->\n+        visit url: 'fourLinksInHeadABCD', ->\n+          linkTagInserted = sinon.spy()\n+          $(document).on 'page:after-link-inserted', linkTagInserted\n+          visit url: 'fourLinksInHeadCDBA', ->\n+            expectedLinkOrder = ['c.css', 'd.css', 'b.css', 'a.css']\n+            expectedLinkOrder.forEach (link, index) ->\n+              assert.equal(index, linkOrderPosition(link), link + ' should be in position ' + index)\n+            assert.equal(linkTagInserted.callCount, 2) # Move A,B\n+            done()\n+\n+      it 'maintains order when moving from a head with links ABCD to links CBDA.', (done) ->\n+        visit url: 'fourLinksInHeadABCD', ->\n+          linkTagInserted = sinon.spy()\n+          $(document).on 'page:after-link-inserted', linkTagInserted\n+          visit url: 'fourLinksInHeadCBDA', ->\n+            expectedLinkOrder = ['c.css', 'b.css', 'd.css', 'a.css']\n+            expectedLinkOrder.forEach (link, index) ->\n+              assert.equal(index, linkOrderPosition(link), link + ' should be in position ' + index)\n+            assert.equal(linkTagInserted.callCount, 2) # Move A,B or A,C\n+            done()\n+\n+      it 'maintains order when moving from a head with links ABCD to links DCBA.', (done) ->\n+        visit url: 'fourLinksInHeadABCD', ->\n+          linkTagInserted = sinon.spy()\n+          $(document).on 'page:after-link-inserted', linkTagInserted\n+          visit url: 'fourLinksInHeadDCBA', ->\n+            expectedLinkOrder = ['d.css', 'c.css', 'b.css', 'a.css']\n+            expectedLinkOrder.forEach (link, index) ->\n+              assert.equal(index, linkOrderPosition(link), link + ' should be in position ' + index)\n+            assert.equal(linkTagInserted.callCount, 3) # Move any 3\n+            done()\n+\n+  describe 'head script tag tracking', ->\n+    it 'dispatches page:after-script-inserted event when inserting a script on navigation', (done) ->\n+      scriptTagInserted = sinon.spy()\n+      $(document).on 'page:after-script-inserted', scriptTagInserted\n+\n+      visit url: 'noScriptsOrLinkInHead', ->\n+        visit url: 'singleScriptInHead', ->\n+          assert.equal(scriptTagInserted.callCount, 1)\n+          done()\n+\n+    it 'inserts script with a new src into empty head on navigation', (done) ->\n+      visit url: 'noScriptsOrLinkInHead', ->\n+        visit url: 'singleScriptInHead', ->\n+          assert(hasScriptOnce('foo.js'), 'Should insert foo.js tag only once.')\n+          done()\n+\n+    it 'inserts script with a new src into existing head on navigation', (done) ->\n+      visit url: 'singleScriptInHead', ->\n+        visit url: 'twoScriptsInHead', ->\n+          assert(hasScriptOnce('bar.js'), 'Should insert bar.js tag only once.')\n+          done()\n+\n+    it 'does not reinsert script with existing src into identical head on navigation', (done) ->\n+      visit url: 'singleScriptInHead', ->\n+        visit url: 'singleScriptInHead', ->\n+          assert(hasScriptOnce('foo.js'), 'Should insert foo.js tag only once.')\n+          done()\n+\n+    it 'does not reinsert script with existing src into existing head on navigation', (done) ->\n+      visit url: 'singleScriptInHead', ->\n+        visit url: 'twoScriptsInHead', ->\n+          assert(hasScriptOnce('foo.js'), 'Should insert foo.js tag only once.')\n+          done()\n+\n+    it 'does not remove script when navigating to a page with an empty head', (done) ->\n+      visit url: 'singleScriptInHead', ->\n+        visit url: 'noScriptsOrLinkInHead', ->\n+          assert(hasScriptOnce('foo.js'), 'Should not remove foo.js tag.')\n+          done()\n+\n+    it 'does not remove script when navigating to a page with the src missing', (done) ->\n+      visit url: 'twoScriptsInHead', ->\n+        visit url: 'singleScriptInHead', ->\n+          assert(hasScriptOnce('foo.js'), 'Should not remove foo.js tag.')\n+          assert(hasScriptOnce('bar.js'), 'Should not remove bar.js tag.')\n+          done()\n+\n+    describe 'executes scripts in the order they are present in the dom of the upstream document', ->\n+      it 'works in order ABC', (done) ->\n+        window.actualExecutionOrder = []\n+        expectedScriptOrder = ['a', 'b', 'c']\n+        visit url: 'threeScriptsInHeadABC', ->\n+          expectedScriptOrder.forEach (script, index) ->\n+            assert.equal(script, actualExecutionOrder[index])\n+          done()\n+\n+      it 'works in order ACB', (done) ->\n+        window.actualExecutionOrder = []\n+        visit url: 'threeScriptsInHeadACB', ->\n+          expectedScriptOrder = ['a', 'c', 'b']\n+          expectedScriptOrder.forEach (script, index) ->\n+            assert.equal(script, actualExecutionOrder[index])\n+          done()\n+\n+      it 'works in order BAC', (done) ->\n+        window.actualExecutionOrder = []\n+        visit url: 'threeScriptsInHeadBAC', ->\n+          expectedScriptOrder = ['b', 'a', 'c']\n+          expectedScriptOrder.forEach (script, index) ->\n+            assert.equal(script, actualExecutionOrder[index])\n+          done()\n+\n+      it 'works in order BCA', (done) ->\n+        window.actualExecutionOrder = []\n+        visit url: 'threeScriptsInHeadBCA', ->\n+          expectedScriptOrder = ['b', 'c', 'a']\n+          expectedScriptOrder.forEach (script, index) ->\n+            assert.equal(script, actualExecutionOrder[index])\n+          done()\n+\n+      it 'works in order CAB', (done) ->\n+        window.actualExecutionOrder = []\n+        visit url: 'threeScriptsInHeadCAB', ->\n+          expectedScriptOrder = ['c', 'a', 'b']\n+          expectedScriptOrder.forEach (script, index) ->\n+            assert.equal(script, actualExecutionOrder[index])\n+          done()\n+\n+      it 'works in order CBA', (done) ->\n+        window.actualExecutionOrder = []\n+        visit url: 'threeScriptsInHeadCBA', ->\n+          expectedScriptOrder = ['c', 'b', 'a']\n+          expectedScriptOrder.forEach (script, index) ->\n+            assert.equal(script, actualExecutionOrder[index])\n+          done()\n+\n+    it 'executes new scripts in the relative order they are present in the dom of the upstream document', (done) ->\n+      window.actualExecutionOrder = []\n+      visit url: 'secondLibraryOnly', ->\n+        assert.equal(actualExecutionOrder[0], 'b')\n+        visit url: 'threeScriptsInHeadABC', ->\n+          assert.equal(actualExecutionOrder[1], 'a')\n+          assert.equal(actualExecutionOrder[2], 'c')\n+          done()\n+\n+    it 'performs a full page refresh when encountering a script with a new src that matches an existing data-turbolinks-track-script-as', (done) ->\n+      visit url: 'singleScriptInHead', ->\n+        visit url: 'singleScriptInHeadWithDifferentSourceButSameName', ->\n+          assert(Turbolinks.fullPageNavigate.called, 'Should perform a full page refresh.')\n+          done()\n+\n+    it 'does not perform a full page refresh when encountering a script with a new src that does not match a data-turbolinks-track-script-as', (done) ->\n+      visit url: 'singleScriptInHead', ->\n+        visit url: 'differentSingleScriptInHead', ->\n+          assert(Turbolinks.fullPageNavigate.notCalled, 'Should not perform a full page refresh.')\n+          done()\n+\n+  describe 'with partial page replacement', ->\n+    it 'script tags are evaluated when they are the subject of a partial replace', (done) ->\n+      window.globalStub = stub()\n+      visit url: 'inlineScriptInBody', options: {partialReplace: true, onlyKeys: ['turbo-area']}, ->\n+        assert(globalStub.calledOnce, 'Script tag was not evaluated :(')\n+        done()\n+","path":"test/javascripts/turbolinks_test.coffee","position":555,"original_position":1057,"commit_id":"6eea29ed9783a992951e3f26bb9373e7b7c5a7c6","original_commit_id":"e6c1fcdd992e94cbb305e51a4673679527704e0d","user":{"login":"MadMub","id":2809870,"avatar_url":"https://avatars.githubusercontent.com/u/2809870?v=3","gravatar_id":"","url":"https://api.github.com/users/MadMub","html_url":"https://github.com/MadMub","followers_url":"https://api.github.com/users/MadMub/followers","following_url":"https://api.github.com/users/MadMub/following{/other_user}","gists_url":"https://api.github.com/users/MadMub/gists{/gist_id}","starred_url":"https://api.github.com/users/MadMub/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/MadMub/subscriptions","organizations_url":"https://api.github.com/users/MadMub/orgs","repos_url":"https://api.github.com/users/MadMub/repos","events_url":"https://api.github.com/users/MadMub/events{/privacy}","received_events_url":"https://api.github.com/users/MadMub/received_events","type":"User","site_admin":false},"body":"I would just load a small A+ compliant one into the Turbograft namespace, I think the global function exported is `Page` why not just do\r\n```\r\nPage.Promise = window.Promise || <polyfill here>\r\n```\r\nThat way you don't conflict with anyone elses' dependencies, just make sure the polyfill of choice doesn't attach `Promise` globally","created_at":"2016-08-23T20:47:09Z","updated_at":"2016-08-23T20:47:09Z","html_url":"https://github.com/Shopify/turbograft/pull/123#discussion_r75947370","pull_request_url":"https://api.github.com/repos/Shopify/turbograft/pulls/123","_links":{"self":{"href":"https://api.github.com/repos/Shopify/turbograft/pulls/comments/75947370"},"html":{"href":"https://github.com/Shopify/turbograft/pull/123#discussion_r75947370"},"pull_request":{"href":"https://api.github.com/repos/Shopify/turbograft/pulls/123"}}},"pull_request":{"url":"https://api.github.com/repos/Shopify/turbograft/pulls/123","id":80870142,"html_url":"https://github.com/Shopify/turbograft/pull/123","diff_url":"https://github.com/Shopify/turbograft/pull/123.diff","patch_url":"https://github.com/Shopify/turbograft/pull/123.patch","issue_url":"https://api.github.com/repos/Shopify/turbograft/issues/123","number":123,"state":"open","locked":false,"title":"Update <head> with new assets on page navigation instead of full page refresh","user":{"login":"justinthec","id":2578036,"avatar_url":"https://avatars.githubusercontent.com/u/2578036?v=3","gravatar_id":"","url":"https://api.github.com/users/justinthec","html_url":"https://github.com/justinthec","followers_url":"https://api.github.com/users/justinthec/followers","following_url":"https://api.github.com/users/justinthec/following{/other_user}","gists_url":"https://api.github.com/users/justinthec/gists{/gist_id}","starred_url":"https://api.github.com/users/justinthec/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/justinthec/subscriptions","organizations_url":"https://api.github.com/users/justinthec/orgs","repos_url":"https://api.github.com/users/justinthec/repos","events_url":"https://api.github.com/users/justinthec/events{/privacy}","received_events_url":"https://api.github.com/users/justinthec/received_events","type":"User","site_admin":false},"body":">Put a PR up anyway\r\n![image](https://cloud.githubusercontent.com/assets/2578036/17571704/4a94edfe-5f1f-11e6-82fe-4531928ff8f9.png)\r\n\r\n@darrenhebner @TheMallen @Shopify/tnt \r\n\r\n@GoodForOneFare @edward \r\n\r\n~~**Note:** JS tests are order dependant due to the DOM being shared and not cleaned up between tests however clearing the body causes more assertion errors. We will continue to look into properly fixing this order dependency issue but for now, we've moved our new tests to a location where it does not cause conflicts.~~\r\n\r\n","created_at":"2016-08-10T21:23:11Z","updated_at":"2016-08-23T20:47:09Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5d760c403f7dd9a0e1b96905552e269afd899210","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/Shopify/turbograft/pulls/123/commits","review_comments_url":"https://api.github.com/repos/Shopify/turbograft/pulls/123/comments","review_comment_url":"https://api.github.com/repos/Shopify/turbograft/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Shopify/turbograft/issues/123/comments","statuses_url":"https://api.github.com/repos/Shopify/turbograft/statuses/6eea29ed9783a992951e3f26bb9373e7b7c5a7c6","head":{"label":"Shopify:delay-navigation-for-defer","ref":"delay-navigation-for-defer","sha":"6eea29ed9783a992951e3f26bb9373e7b7c5a7c6","user":{"login":"Shopify","id":8085,"avatar_url":"https://avatars.githubusercontent.com/u/8085?v=3","gravatar_id":"","url":"https://api.github.com/users/Shopify","html_url":"https://github.com/Shopify","followers_url":"https://api.github.com/users/Shopify/followers","following_url":"https://api.github.com/users/Shopify/following{/other_user}","gists_url":"https://api.github.com/users/Shopify/gists{/gist_id}","starred_url":"https://api.github.com/users/Shopify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shopify/subscriptions","organizations_url":"https://api.github.com/users/Shopify/orgs","repos_url":"https://api.github.com/users/Shopify/repos","events_url":"https://api.github.com/users/Shopify/events{/privacy}","received_events_url":"https://api.github.com/users/Shopify/received_events","type":"Organization","site_admin":false},"repo":{"id":23920094,"name":"turbograft","full_name":"Shopify/turbograft","owner":{"login":"Shopify","id":8085,"avatar_url":"https://avatars.githubusercontent.com/u/8085?v=3","gravatar_id":"","url":"https://api.github.com/users/Shopify","html_url":"https://github.com/Shopify","followers_url":"https://api.github.com/users/Shopify/followers","following_url":"https://api.github.com/users/Shopify/following{/other_user}","gists_url":"https://api.github.com/users/Shopify/gists{/gist_id}","starred_url":"https://api.github.com/users/Shopify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shopify/subscriptions","organizations_url":"https://api.github.com/users/Shopify/orgs","repos_url":"https://api.github.com/users/Shopify/repos","events_url":"https://api.github.com/users/Shopify/events{/privacy}","received_events_url":"https://api.github.com/users/Shopify/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Shopify/turbograft","description":"Hard fork of turbolinks, adding partial page replacement strategies, and utilities.","fork":false,"url":"https://api.github.com/repos/Shopify/turbograft","forks_url":"https://api.github.com/repos/Shopify/turbograft/forks","keys_url":"https://api.github.com/repos/Shopify/turbograft/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Shopify/turbograft/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Shopify/turbograft/teams","hooks_url":"https://api.github.com/repos/Shopify/turbograft/hooks","issue_events_url":"https://api.github.com/repos/Shopify/turbograft/issues/events{/number}","events_url":"https://api.github.com/repos/Shopify/turbograft/events","assignees_url":"https://api.github.com/repos/Shopify/turbograft/assignees{/user}","branches_url":"https://api.github.com/repos/Shopify/turbograft/branches{/branch}","tags_url":"https://api.github.com/repos/Shopify/turbograft/tags","blobs_url":"https://api.github.com/repos/Shopify/turbograft/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Shopify/turbograft/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Shopify/turbograft/git/refs{/sha}","trees_url":"https://api.github.com/repos/Shopify/turbograft/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Shopify/turbograft/statuses/{sha}","languages_url":"https://api.github.com/repos/Shopify/turbograft/languages","stargazers_url":"https://api.github.com/repos/Shopify/turbograft/stargazers","contributors_url":"https://api.github.com/repos/Shopify/turbograft/contributors","subscribers_url":"https://api.github.com/repos/Shopify/turbograft/subscribers","subscription_url":"https://api.github.com/repos/Shopify/turbograft/subscription","commits_url":"https://api.github.com/repos/Shopify/turbograft/commits{/sha}","git_commits_url":"https://api.github.com/repos/Shopify/turbograft/git/commits{/sha}","comments_url":"https://api.github.com/repos/Shopify/turbograft/comments{/number}","issue_comment_url":"https://api.github.com/repos/Shopify/turbograft/issues/comments{/number}","contents_url":"https://api.github.com/repos/Shopify/turbograft/contents/{+path}","compare_url":"https://api.github.com/repos/Shopify/turbograft/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Shopify/turbograft/merges","archive_url":"https://api.github.com/repos/Shopify/turbograft/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Shopify/turbograft/downloads","issues_url":"https://api.github.com/repos/Shopify/turbograft/issues{/number}","pulls_url":"https://api.github.com/repos/Shopify/turbograft/pulls{/number}","milestones_url":"https://api.github.com/repos/Shopify/turbograft/milestones{/number}","notifications_url":"https://api.github.com/repos/Shopify/turbograft/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Shopify/turbograft/labels{/name}","releases_url":"https://api.github.com/repos/Shopify/turbograft/releases{/id}","deployments_url":"https://api.github.com/repos/Shopify/turbograft/deployments","created_at":"2014-09-11T13:47:46Z","updated_at":"2016-07-27T23:50:04Z","pushed_at":"2016-08-23T20:45:21Z","git_url":"git://github.com/Shopify/turbograft.git","ssh_url":"git@github.com:Shopify/turbograft.git","clone_url":"https://github.com/Shopify/turbograft.git","svn_url":"https://github.com/Shopify/turbograft","homepage":"","size":621,"stargazers_count":151,"watchers_count":151,"language":"CoffeeScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":14,"mirror_url":null,"open_issues_count":25,"forks":14,"open_issues":25,"watchers":151,"default_branch":"master"}},"base":{"label":"Shopify:master","ref":"master","sha":"bf5bc64e02e7ecb0bacb263a410aec8e09bbbd88","user":{"login":"Shopify","id":8085,"avatar_url":"https://avatars.githubusercontent.com/u/8085?v=3","gravatar_id":"","url":"https://api.github.com/users/Shopify","html_url":"https://github.com/Shopify","followers_url":"https://api.github.com/users/Shopify/followers","following_url":"https://api.github.com/users/Shopify/following{/other_user}","gists_url":"https://api.github.com/users/Shopify/gists{/gist_id}","starred_url":"https://api.github.com/users/Shopify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shopify/subscriptions","organizations_url":"https://api.github.com/users/Shopify/orgs","repos_url":"https://api.github.com/users/Shopify/repos","events_url":"https://api.github.com/users/Shopify/events{/privacy}","received_events_url":"https://api.github.com/users/Shopify/received_events","type":"Organization","site_admin":false},"repo":{"id":23920094,"name":"turbograft","full_name":"Shopify/turbograft","owner":{"login":"Shopify","id":8085,"avatar_url":"https://avatars.githubusercontent.com/u/8085?v=3","gravatar_id":"","url":"https://api.github.com/users/Shopify","html_url":"https://github.com/Shopify","followers_url":"https://api.github.com/users/Shopify/followers","following_url":"https://api.github.com/users/Shopify/following{/other_user}","gists_url":"https://api.github.com/users/Shopify/gists{/gist_id}","starred_url":"https://api.github.com/users/Shopify/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Shopify/subscriptions","organizations_url":"https://api.github.com/users/Shopify/orgs","repos_url":"https://api.github.com/users/Shopify/repos","events_url":"https://api.github.com/users/Shopify/events{/privacy}","received_events_url":"https://api.github.com/users/Shopify/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Shopify/turbograft","description":"Hard fork of turbolinks, adding partial page replacement strategies, and utilities.","fork":false,"url":"https://api.github.com/repos/Shopify/turbograft","forks_url":"https://api.github.com/repos/Shopify/turbograft/forks","keys_url":"https://api.github.com/repos/Shopify/turbograft/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Shopify/turbograft/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Shopify/turbograft/teams","hooks_url":"https://api.github.com/repos/Shopify/turbograft/hooks","issue_events_url":"https://api.github.com/repos/Shopify/turbograft/issues/events{/number}","events_url":"https://api.github.com/repos/Shopify/turbograft/events","assignees_url":"https://api.github.com/repos/Shopify/turbograft/assignees{/user}","branches_url":"https://api.github.com/repos/Shopify/turbograft/branches{/branch}","tags_url":"https://api.github.com/repos/Shopify/turbograft/tags","blobs_url":"https://api.github.com/repos/Shopify/turbograft/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Shopify/turbograft/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Shopify/turbograft/git/refs{/sha}","trees_url":"https://api.github.com/repos/Shopify/turbograft/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Shopify/turbograft/statuses/{sha}","languages_url":"https://api.github.com/repos/Shopify/turbograft/languages","stargazers_url":"https://api.github.com/repos/Shopify/turbograft/stargazers","contributors_url":"https://api.github.com/repos/Shopify/turbograft/contributors","subscribers_url":"https://api.github.com/repos/Shopify/turbograft/subscribers","subscription_url":"https://api.github.com/repos/Shopify/turbograft/subscription","commits_url":"https://api.github.com/repos/Shopify/turbograft/commits{/sha}","git_commits_url":"https://api.github.com/repos/Shopify/turbograft/git/commits{/sha}","comments_url":"https://api.github.com/repos/Shopify/turbograft/comments{/number}","issue_comment_url":"https://api.github.com/repos/Shopify/turbograft/issues/comments{/number}","contents_url":"https://api.github.com/repos/Shopify/turbograft/contents/{+path}","compare_url":"https://api.github.com/repos/Shopify/turbograft/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Shopify/turbograft/merges","archive_url":"https://api.github.com/repos/Shopify/turbograft/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Shopify/turbograft/downloads","issues_url":"https://api.github.com/repos/Shopify/turbograft/issues{/number}","pulls_url":"https://api.github.com/repos/Shopify/turbograft/pulls{/number}","milestones_url":"https://api.github.com/repos/Shopify/turbograft/milestones{/number}","notifications_url":"https://api.github.com/repos/Shopify/turbograft/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Shopify/turbograft/labels{/name}","releases_url":"https://api.github.com/repos/Shopify/turbograft/releases{/id}","deployments_url":"https://api.github.com/repos/Shopify/turbograft/deployments","created_at":"2014-09-11T13:47:46Z","updated_at":"2016-07-27T23:50:04Z","pushed_at":"2016-08-23T20:45:21Z","git_url":"git://github.com/Shopify/turbograft.git","ssh_url":"git@github.com:Shopify/turbograft.git","clone_url":"https://github.com/Shopify/turbograft.git","svn_url":"https://github.com/Shopify/turbograft","homepage":"","size":621,"stargazers_count":151,"watchers_count":151,"language":"CoffeeScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":14,"mirror_url":null,"open_issues_count":25,"forks":14,"open_issues":25,"watchers":151,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Shopify/turbograft/pulls/123"},"html":{"href":"https://github.com/Shopify/turbograft/pull/123"},"issue":{"href":"https://api.github.com/repos/Shopify/turbograft/issues/123"},"comments":{"href":"https://api.github.com/repos/Shopify/turbograft/issues/123/comments"},"review_comments":{"href":"https://api.github.com/repos/Shopify/turbograft/pulls/123/comments"},"review_comment":{"href":"https://api.github.com/repos/Shopify/turbograft/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Shopify/turbograft/pulls/123/commits"},"statuses":{"href":"https://api.github.com/repos/Shopify/turbograft/statuses/6eea29ed9783a992951e3f26bb9373e7b7c5a7c6"}}}}
{"actor":{"display_login":"MadMub"}}