-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Inline scripts should always execute after scripts are downloaded Fixes #151
- Loading branch information
1 parent
65e3153
commit 0c6cff8
Showing
11 changed files
with
492 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#= require ./fake_script | ||
|
||
window.fakeDocument = (scriptSources) -> | ||
nodes = (fakeScript(src) for src in scriptSources) | ||
newNodes = [] | ||
|
||
return { | ||
createdScripts: newNodes | ||
head: { | ||
appendChild: () -> {} | ||
} | ||
|
||
createElement: () -> | ||
script = fakeScript() | ||
newNodes.push(script) | ||
script | ||
|
||
createTextNode: () -> {} | ||
|
||
querySelectorAll: -> nodes | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
window.fakeScript = (src) -> | ||
listeners = [] | ||
node = { | ||
'data-turbolinks-track': src | ||
attributes: [{name: 'src', value: src}] | ||
isLoaded: false | ||
src: src | ||
nodeName: 'SCRIPT' | ||
|
||
appendChild: () -> {} | ||
|
||
setAttribute: (name, value) -> | ||
if name == 'src' | ||
@src = value | ||
@attributes.push({name: name, value: value}) | ||
|
||
addEventListener: (eventName, listener) -> | ||
return if eventName != 'load' | ||
listeners.push(listener) | ||
|
||
fireLoaded: () -> | ||
listener({type: 'load'}) for listener in listeners | ||
new Promise (resolve) -> | ||
node.isLoaded = true | ||
setTimeout -> resolve(node) | ||
|
||
removeEventListener: () -> {} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
#= require ./fake_document | ||
|
||
describe 'TurboHead', -> | ||
activeDocument = null | ||
promiseQueue = null | ||
requests = [] | ||
|
||
assertScriptCount = (size, message) -> | ||
promiseQueue = promiseQueue.then -> | ||
assert.lengthOf(activeDocument.createdScripts, size, message) | ||
|
||
finishScriptDownload = -> | ||
promiseQueue = promiseQueue.then -> | ||
new Promise (resolve) -> | ||
unloaded = activeDocument.createdScripts.filter (script) -> | ||
!script.isLoaded | ||
|
||
unloaded[0].fireLoaded().then -> | ||
setTimeout -> resolve(unloaded[0]) | ||
|
||
newRequest = (requestScripts) -> | ||
promiseQueue = promiseQueue.then -> | ||
new Promise (resolve) -> | ||
head = new TurboHead( | ||
activeDocument, | ||
fakeDocument(requestScripts) | ||
) | ||
|
||
request = head.waitForAssets() | ||
request.isInProgress = true | ||
request.isFulfilled = false | ||
request.isRejected = false | ||
request | ||
.then (result) -> | ||
request.isInProgress = false | ||
request.isCanceled = Boolean(result.isCanceled) | ||
request.isFulfilled = !request.isCanceled | ||
.catch -> request.isRejected = true | ||
requests.push(request) | ||
|
||
setTimeout(resolve, 50) # Wait for beginning of first script download. | ||
|
||
beforeEach -> | ||
activeDocument = fakeDocument([]) # Start with no scripts. | ||
promiseQueue = Promise.resolve() | ||
requests = [] | ||
|
||
afterEach -> | ||
TurboHead._testAPI.reset() | ||
|
||
describe 'script download queue', -> | ||
it 'downloads scripts in sequence', -> | ||
newRequest(['a.js', 'b.js', 'c.js']) | ||
assertScriptCount(1, 'first script download should be in progress') | ||
finishScriptDownload() | ||
.then (script) -> assert.equal(script.src, 'a.js') | ||
|
||
assertScriptCount(2, 'first download complete should trigger second') | ||
finishScriptDownload() | ||
.then (script) -> assert.equal(script.src, 'b.js') | ||
|
||
assertScriptCount(3, 'second download complete should trigger third') | ||
finishScriptDownload() | ||
.then (script) -> | ||
assert.equal(script.src, 'c.js') | ||
assert.isTrue( | ||
requests[0].isFulfilled, | ||
'all downloads complete should resolve request' | ||
) | ||
|
||
describe 'superceded requests', -> | ||
it 'cancels stale requests', -> | ||
newRequest(['d.js']) | ||
newRequest([]).then -> | ||
assert.isTrue(requests[0].isCanceled) | ||
|
||
it 'waits for previously queued scripts before starting new request', -> | ||
newRequest(['a.js', 'b.js']) | ||
newRequest([]) | ||
finishScriptDownload() | ||
finishScriptDownload() | ||
assertScriptCount(2, 'duplicate script elements should not be created') | ||
.then -> | ||
assert.isTrue(requests[0].isCanceled) | ||
assert.isTrue(requests[1].isFulfilled) | ||
|
||
it 'does not add duplicate script tags for new requests', -> | ||
newRequest(['a.js', 'b.js']) | ||
newRequest(['a.js', 'b.js']) | ||
assertScriptCount(1, 'first script should be downloading').then -> | ||
assert.isTrue(requests[1].isInProgress) | ||
finishScriptDownload() | ||
finishScriptDownload() | ||
.then -> | ||
assertScriptCount(2, 'duplicate script elements were created') | ||
assert.isTrue(requests[1].isFulfilled) | ||
|
||
it 'enqueues new scripts for new requests', -> | ||
newRequest(['a.js', 'b.js']) | ||
newRequest(['b.js', 'c.js', 'd.js']) | ||
finishScriptDownload() | ||
finishScriptDownload().then -> | ||
assert.isTrue(requests[1].isInProgress) | ||
finishScriptDownload().then -> | ||
assert.isTrue(requests[1].isInProgress) | ||
finishScriptDownload().then (script) -> | ||
assertScriptCount(4, 'second request\'s assets should be downloaded') | ||
assert.equal( | ||
script.src, 'd.js', | ||
'last queued script should be last downloaded' | ||
) | ||
assert.isTrue(requests[1].isFulfilled) | ||
|
||
it 'does not reload completed scripts for new requests', -> | ||
newRequest(['a.js', 'b.js']) | ||
finishScriptDownload() | ||
finishScriptDownload().then -> | ||
assertScriptCount(2) | ||
assert.isTrue(requests[0].isFulfilled) | ||
newRequest(['a.js', 'b.js']).then -> | ||
assertScriptCount(2) | ||
assert.isTrue(requests[1].isFulfilled) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.