diff --git a/Gruntfile.js b/Gruntfile.js index 956113503..702b1f2df 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,4 +1,12 @@ "use strict"; +var fs = require('fs'); +var build = (function(){ + // travis testing + if (process.env && process.env.BUILD) return process.env.BUILD == 'default' ? 'all' : 'nocompat'; + // local testing + else return process.argv[2] == null || process.argv[2] == 'all' ? 'all' : 'nocompat'; +})(); +var htmlFileServer = require('./Tests/httpserver.js')(build); module.exports = function(grunt) { diff --git a/Specs/Utilities/DOMReady.js b/Specs/Utilities/DOMReady.js index 5a8d15fc5..d1ffe6d09 100644 --- a/Specs/Utilities/DOMReady.js +++ b/Specs/Utilities/DOMReady.js @@ -6,30 +6,96 @@ provides: ~ ... */ -/* todo -document.addListener = function(type, fn){ - if (this.addEventListener) this.addEventListener(type, fn, false); - else this.attachEvent('on' + type, fn); - return this; -}; - -document.removeListener = function(type, fn){ - if (this.removeEventListener) this.removeEventListener(type, fn, false); - else this.detachEvent('on' + type, fn); - return this; -}; - - -window.fireEvent = -document.fireEvent = function(type){ - if (type == 'domready') - for (var i = 0; i < domreadyCallbacks.length; ++i){ +describe("DOMReady", function(){ + + var win, frame, cb, ready; + function checkStatus(){ + ready = win && win.callbackFired; + if (ready) cb(); + return ready; } - domreadyCallbacks[i](); -}; -window.addEvent = function(){}; + function newFrame(url){ + var iframe = new IFrame({ + src: 'specsserver/' + url + }); + document.getElement('body').adopt(iframe); + return iframe; + } + + beforeEach(function(){ + cb = jasmine.createSpy('DOMReady!'); + }); + + afterEach(function(){ + frame.destroy(); + win = cb = frame = ready = null; + }); + + it('should fire DOMReady, after flushing, when the DOM is ready', function(){ + frame = newFrame('DOMReady.flushA.html~DOMReady.flushB.html'); + frame.addEvent('load', function(){ + win = frame.contentWindow; + expect(win.moments[0]).toEqual('loading'); + expect(win.moments[1]).toEqual('loading'); + expect(win.moments[2] == 'interactive' || win.moments[2] == 'complete').toBeTruthy(); + }); + + waitsFor(function(){ + return checkStatus(); + }, "the iframe to load", 8000); + runs(function(){ + expect(cb).toHaveBeenCalled(); + }); + }); + + it('should fire DOMReady when the DOM is ready', function(){ + frame = newFrame('DOMReady.head.html'); + frame.addEvent('load', function(){ + win = frame.contentWindow; + }); + waitsFor(function(){ + return checkStatus(); + }, "the iframe to load", 1500); + runs(function(){ + expect(cb).toHaveBeenCalled(); + }); + }); + + it('should fire DOMReady when a new `addEvent("domready"` is added', function(){ + frame = newFrame('DOMReady.onAdd.html'); + frame.addEvent('load', function(){ + win = frame.contentWindow; + win.addEvent('domready', win.callback); + }); + waitsFor(function(){ + return checkStatus(); + }, "the iframe to load", 1500); + runs(function(){ + expect(cb).toHaveBeenCalled(); + }); + }); + + it('should fire when MooTools was loaded into a already-ready page', function(){ + frame = newFrame('DOMReady.delayed.html'); + var ready; + frame.addEvent('load', function(){ + win = frame.contentWindow; + expect(win.MooTools).toBeFalsy(); // because MooTools should not be loaded yet + var i = setInterval(function(){ + if (win.addEvent && win.callback){ + win.addEvent('domready', win.callback); + if (ready) clearInterval(i); + } + }, 50); + }); + waitsFor(function(){ + return checkStatus(); + }, "the iframe to load and MooTools to be deployed", 6000); + runs(function(){ + expect(cb).toHaveBeenCalled(); + }); + }); + +}); -var Element = this.Element || {}; -Element.Events = {}; -*/ diff --git a/Tests/DOMReady/DOMReady.delayed.html b/Tests/DOMReady/DOMReady.delayed.html new file mode 100644 index 000000000..09e644609 --- /dev/null +++ b/Tests/DOMReady/DOMReady.delayed.html @@ -0,0 +1,27 @@ + + + + + Add MooTools when page is already ready + + + + + + diff --git a/Tests/DOMReady/DOMReady.flushA.html b/Tests/DOMReady/DOMReady.flushA.html new file mode 100644 index 000000000..6071effde --- /dev/null +++ b/Tests/DOMReady/DOMReady.flushA.html @@ -0,0 +1,18 @@ + + + + + Flushed page scenario + + + diff --git a/Tests/DOMReady/DOMReady.flushB.html b/Tests/DOMReady/DOMReady.flushB.html new file mode 100644 index 000000000..806de5940 --- /dev/null +++ b/Tests/DOMReady/DOMReady.flushB.html @@ -0,0 +1,6 @@ + +
body added...
+ + diff --git a/Tests/DOMReady/DOMReady.head.html b/Tests/DOMReady/DOMReady.head.html new file mode 100644 index 000000000..f3b6b2f3b --- /dev/null +++ b/Tests/DOMReady/DOMReady.head.html @@ -0,0 +1,21 @@ + + + + + Normal DOMReady scenario + + + + + + + + + diff --git a/Tests/DOMReady/DOMReady.onAdd.html b/Tests/DOMReady/DOMReady.onAdd.html new file mode 100644 index 000000000..d751f6dc3 --- /dev/null +++ b/Tests/DOMReady/DOMReady.onAdd.html @@ -0,0 +1,19 @@ + + + + + DOMReady added when page is already loaded + + + + + + + + diff --git a/Tests/gruntfile-options.js b/Tests/gruntfile-options.js index 094a18383..de5a9b272 100644 --- a/Tests/gruntfile-options.js +++ b/Tests/gruntfile-options.js @@ -66,7 +66,15 @@ var karmaOptions = { captureTimeout: 60000 * 2, singleRun: true, frameworks: ['jasmine', 'sinon'], - files: ['Tests/Utilities/*.js', 'mootools-*.js'], + files: [ + 'Tests/Utilities/*.js', + 'mootools-*.js', + {pattern: 'Source/**/*.*', included: false, served: true}, + {pattern: 'Tests/DOMReady/*.*', included: false, served: true} + ], + proxies: { + '/specsserver/': 'http://localhost:9000/' + }, sauceLabs: { username: process.env.SAUCE_USERNAME, accessKey: process.env.SAUCE_ACCESS_KEY, diff --git a/Tests/httpserver.js b/Tests/httpserver.js new file mode 100644 index 000000000..673ef40e6 --- /dev/null +++ b/Tests/httpserver.js @@ -0,0 +1,37 @@ +"use strict"; + +var fs = require('fs'); +var path = require('path'); +var http = require('http'); + +module.exports = function(build){ + + var getFileContent = function(url, callback){ + fs.readFile(url, 'utf-8', function (err, content) { + if (err) return console.log(err); + content = content.replace('mootoolsPath', '/base/mootools-' + build); + callback(content); + }); + } + + http.createServer(function(req, res){ + if (req.url.indexOf('~') != -1){ // multiple files to send as chunks + var partials = req.url.split('~'); + partials.push(null); // res.end() + res.writeHead(200, {'Content-Type': 'text/html'}); + partials.forEach(function(file, i){ + setTimeout(function(){ + if (!file) res.end(''); + else getFileContent(path.join(__dirname, '/DOMReady/', file), function(data){ + res.write(data); + }); + }, 2000 * i + 1); + }) + } else { // single files + getFileContent(path.join(__dirname, '/DOMReady/', req.url), function(data){ + res.end(data); + }); + } + }).listen(9000); +} + diff --git a/package.json b/package.json index 4e52722a8..2d873198e 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "karma-firefox-launcher": "~0.1.3", "karma-ie-launcher": "~0.1", "karma-safari-launcher": "~0.1", + "path": "^0.11.14", "js-yaml": "^3.0.2" } }