diff --git a/Rakefile b/Rakefile index 5584402..b5c327a 100644 --- a/Rakefile +++ b/Rakefile @@ -46,7 +46,7 @@ Rake::PackageTask.new('prototype', PROTOTYPE_VERSION) do |package| end desc "Builds the distribution, runs the JavaScript unit tests and collects their results." -task :test => [:dist, :test_units] +task :test => [:build_tests, :dist, :test_units] require 'test/lib/jstest' desc "Runs all the JavaScript unit tests and collects the results" @@ -58,9 +58,9 @@ JavaScriptTestTask.new(:test_units) do |t| t.mount("/dist") t.mount("/test") - Dir["test/unit/*.html"].sort.each do |test_file| + Dir["test/unit/tmp/*_test.html"].sort.each do |test_file| tests = testcases ? { :url => "/#{test_file}", :testcases => testcases } : "/#{test_file}" - test_filename = test_file[/.*\/(.+?)\.html/, 1] + test_filename = test_file[/.*\/(.+?)_test\.html/, 1] t.run(tests) unless tests_to_run && !tests_to_run.include?(test_filename) end @@ -69,6 +69,8 @@ JavaScriptTestTask.new(:test_units) do |t| end end -task :clean_package_source do - rm_rf File.join(PROTOTYPE_PKG_DIR, "prototype-#{PROTOTYPE_VERSION}") -end +task :build_tests do + Dir["test/unit/*_test.js"].each do |test_file| + TestBuilder.new(test_file).render + end +end \ No newline at end of file diff --git a/test/lib/jstest.rb b/test/lib/jstest.rb index 8eb1e87..ac0796a 100644 --- a/test/lib/jstest.rb +++ b/test/lib/jstest.rb @@ -3,6 +3,7 @@ require 'thread' require 'webrick' require 'fileutils' include FileUtils +require 'erb' class Browser def supported?; true; end @@ -380,3 +381,38 @@ class JavaScriptTestTask < ::Rake::TaskLib @browsers< + + + Prototype Unit test file | <%= @title %> + + + + + + + + + +

Prototype Unit test file

+

<%= @title %>

+ + + + +
+ + +<%= @fixtures %> + + + + diff --git a/test/unit/.DS_Store b/test/unit/.DS_Store new file mode 100644 index 0000000..2cfd152 Binary files /dev/null and b/test/unit/.DS_Store differ diff --git a/test/unit/ajax.html b/test/unit/ajax.html deleted file mode 100644 index 55e3f43..0000000 --- a/test/unit/ajax.html +++ /dev/null @@ -1,451 +0,0 @@ - - - - Prototype Unit test file - - - - - - -

Prototype Unit test file

-

- Test of utility functions in ajax.js -

- - -
-
-
- - - - - diff --git a/test/unit/ajax_test.js b/test/unit/ajax_test.js new file mode 100644 index 0000000..3c1441c --- /dev/null +++ b/test/unit/ajax_test.js @@ -0,0 +1,422 @@ +var Fixtures = { + js: { + responseBody: '$("content").update("

Hello world!

");', + 'Content-Type': ' text/javascript ' + }, + + html: { + responseBody: "Pack my box with five dozen liquor jugs! " + + "Oh, how quickly daft jumping zebras vex..." + }, + + xml: { + responseBody: 'bar', + 'Content-Type': 'application/xml' + }, + + json: { + responseBody: '{\n\r"test": 123}', + 'Content-Type': 'application/json' + }, + + jsonWithoutContentType: { + responseBody: '{"test": 123}' + }, + + invalidJson: { + responseBody: '{});window.attacked = true;({}', + 'Content-Type': 'application/json' + }, + + headerJson: { + 'X-JSON': '{"test": "hello #éà"}' + } +}; + +var extendDefault = function(options) { + return Object.extend({ + asynchronous: false, + method: 'get', + onException: function(e) { throw e } + }, options); +}; + +var responderCounter = 0; + +// lowercase comparison because of MSIE which presents HTML tags in uppercase +var sentence = ("Pack my box with five dozen liquor jugs! " + +"Oh, how quickly daft jumping zebras vex...").toLowerCase(); + +var message = 'You must be running your tests from rake to test this feature.'; + +new Test.Unit.Runner({ + setup: function() { + $('content').update(''); + $('content2').update(''); + }, + + teardown: function() { + // hack to cleanup responders + Ajax.Responders.responders = [Ajax.Responders.responders[0]]; + }, + + testSynchronousRequest: function() { + this.assertEqual("", $("content").innerHTML); + + this.assertEqual(0, Ajax.activeRequestCount); + new Ajax.Request("../fixtures/hello.js", { + asynchronous: false, + method: 'GET', + evalJS: 'force' + }); + this.assertEqual(0, Ajax.activeRequestCount); + + var h2 = $("content").firstChild; + this.assertEqual("Hello world!", h2.innerHTML); + }, + + testAsynchronousRequest: function() { + this.assertEqual("", $("content").innerHTML); + + new Ajax.Request("../fixtures/hello.js", { + asynchronous: true, + method: 'get', + evalJS: 'force' + }); + this.wait(1000, function() { + var h2 = $("content").firstChild; + this.assertEqual("Hello world!", h2.innerHTML); + }); + }, + + testUpdater: function() { + this.assertEqual("", $("content").innerHTML); + + new Ajax.Updater("content", "../fixtures/content.html", { method:'get' }); + + this.wait(1000, function() { + this.assertEqual(sentence, $("content").innerHTML.strip().toLowerCase()); + + $('content').update(''); + this.assertEqual("", $("content").innerHTML); + + new Ajax.Updater({ success:"content", failure:"content2" }, + "../fixtures/content.html", { method:'get', parameters:{ pet:'monkey' } }); + + new Ajax.Updater("", "../fixtures/content.html", { method:'get', parameters:"pet=monkey" }); + + this.wait(1000, function() { + this.assertEqual(sentence, $("content").innerHTML.strip().toLowerCase()); + this.assertEqual("", $("content2").innerHTML); + }); + }); + }, + + testUpdaterWithInsertion: function() { + $('content').update(); + new Ajax.Updater("content", "../fixtures/content.html", { method:'get', insertion: Insertion.Top }); + this.wait(1000, function() { + this.assertEqual(sentence, $("content").innerHTML.strip().toLowerCase()); + $('content').update(); + new Ajax.Updater("content", "../fixtures/content.html", { method:'get', insertion: 'bottom' }); + this.wait(1000, function() { + this.assertEqual(sentence, $("content").innerHTML.strip().toLowerCase()); + + $('content').update(); + new Ajax.Updater("content", "../fixtures/content.html", { method:'get', insertion: 'after' }); + this.wait(1000, function() { + this.assertEqual('five dozen', $("content").next().innerHTML.strip().toLowerCase()); + }); + }); + }); + }, + + testUpdaterOptions: function() { + var options = { + method: 'get', + asynchronous: false, + evalJS: 'force', + onComplete: Prototype.emptyFunction + } + var request = new Ajax.Updater("content", "../fixtures/hello.js", options); + request.options.onComplete = function() {}; + this.assertIdentical(Prototype.emptyFunction, options.onComplete); + }, + + testResponders: function(){ + // check for internal responder + this.assertEqual(1, Ajax.Responders.responders.length); + + var dummyResponder = { + onComplete: function(req) { /* dummy */ } + }; + + Ajax.Responders.register(dummyResponder); + this.assertEqual(2, Ajax.Responders.responders.length); + + // don't add twice + Ajax.Responders.register(dummyResponder); + this.assertEqual(2, Ajax.Responders.responders.length); + + Ajax.Responders.unregister(dummyResponder); + this.assertEqual(1, Ajax.Responders.responders.length); + + var responder = { + onCreate: function(req){ responderCounter++ }, + onLoading: function(req){ responderCounter++ }, + onComplete: function(req){ responderCounter++ } + }; + Ajax.Responders.register(responder); + + this.assertEqual(0, responderCounter); + this.assertEqual(0, Ajax.activeRequestCount); + new Ajax.Request("../fixtures/content.html", { method:'get', parameters:"pet=monkey" }); + this.assertEqual(1, responderCounter); + this.assertEqual(1, Ajax.activeRequestCount); + + this.wait(1000,function() { + this.assertEqual(3, responderCounter); + this.assertEqual(0, Ajax.activeRequestCount); + }); + }, + + testEvalResponseShouldBeCalledBeforeOnComplete: function() { + if (this.isRunningFromRake) { + this.assertEqual("", $("content").innerHTML); + + this.assertEqual(0, Ajax.activeRequestCount); + new Ajax.Request("../fixtures/hello.js", extendDefault({ + onComplete: function(response) { this.assertNotEqual("", $("content").innerHTML) }.bind(this) + })); + this.assertEqual(0, Ajax.activeRequestCount); + + var h2 = $("content").firstChild; + this.assertEqual("Hello world!", h2.innerHTML); + } else { + this.info(message); + } + }, + + testContentTypeSetForSimulatedVerbs: function() { + if (this.isRunningFromRake) { + new Ajax.Request('/inspect', extendDefault({ + method: 'put', + contentType: 'application/bogus', + onComplete: function(response) { + this.assertEqual('application/bogus; charset=UTF-8', response.responseJSON.headers['content-type']); + }.bind(this) + })); + } else { + this.info(message); + } + }, + + testOnCreateCallback: function() { + new Ajax.Request("../fixtures/content.html", extendDefault({ + onCreate: function(transport) { this.assertEqual(0, transport.readyState) }.bind(this), + onComplete: function(transport) { this.assertNotEqual(0, transport.readyState) }.bind(this) + })); + }, + + testEvalJS: function() { + if (this.isRunningFromRake) { + + $('content').update(); + new Ajax.Request("/response", extendDefault({ + parameters: Fixtures.js, + onComplete: function(transport) { + var h2 = $("content").firstChild; + this.assertEqual("Hello world!", h2.innerHTML); + }.bind(this) + })); + + $('content').update(); + new Ajax.Request("/response", extendDefault({ + evalJS: false, + parameters: Fixtures.js, + onComplete: function(transport) { + this.assertEqual("", $("content").innerHTML); + }.bind(this) + })); + } else { + this.info(message); + } + + $('content').update(); + new Ajax.Request("../fixtures/hello.js", extendDefault({ + evalJS: 'force', + onComplete: function(transport) { + var h2 = $("content").firstChild; + this.assertEqual("Hello world!", h2.innerHTML); + }.bind(this) + })); + }, + + testCallbacks: function() { + var options = extendDefault({ + onCreate: function(transport) { this.assertInstanceOf(Ajax.Response, transport) }.bind(this) + }); + + Ajax.Request.Events.each(function(state){ + options['on' + state] = options.onCreate; + }); + + new Ajax.Request("../fixtures/content.html", options); + }, + + testResponseText: function() { + new Ajax.Request("../fixtures/empty.html", extendDefault({ + onComplete: function(transport) { this.assertEqual('', transport.responseText) }.bind(this) + })); + + new Ajax.Request("../fixtures/content.html", extendDefault({ + onComplete: function(transport) { this.assertEqual(sentence, transport.responseText.toLowerCase()) }.bind(this) + })); + }, + + testResponseXML: function() { + if (this.isRunningFromRake) { + new Ajax.Request("/response", extendDefault({ + parameters: Fixtures.xml, + onComplete: function(transport) { + this.assertEqual('foo', transport.responseXML.getElementsByTagName('name')[0].getAttribute('attr')) + }.bind(this) + })); + } else { + this.info(message); + } + }, + + testResponseJSON: function() { + if (this.isRunningFromRake) { + new Ajax.Request("/response", extendDefault({ + parameters: Fixtures.json, + onComplete: function(transport) { this.assertEqual(123, transport.responseJSON.test) }.bind(this) + })); + + new Ajax.Request("/response", extendDefault({ + parameters: { + 'Content-Length': 0, + 'Content-Type': 'application/json' + }, + onComplete: function(transport) { this.assertNull(transport.responseJSON) }.bind(this) + })); + + new Ajax.Request("/response", extendDefault({ + evalJSON: false, + parameters: Fixtures.json, + onComplete: function(transport) { this.assertNull(transport.responseJSON) }.bind(this) + })); + + new Ajax.Request("/response", extendDefault({ + parameters: Fixtures.jsonWithoutContentType, + onComplete: function(transport) { this.assertNull(transport.responseJSON) }.bind(this) + })); + + new Ajax.Request("/response", extendDefault({ + sanitizeJSON: true, + parameters: Fixtures.invalidJson, + onException: function(request, error) { + this.assert(error.message.include('Badly formed JSON string')); + this.assertInstanceOf(Ajax.Request, request); + }.bind(this) + })); + } else { + this.info(message); + } + + new Ajax.Request("../fixtures/data.json", extendDefault({ + evalJSON: 'force', + onComplete: function(transport) { this.assertEqual(123, transport.responseJSON.test) }.bind(this) + })); + }, + + testHeaderJSON: function() { + if (this.isRunningFromRake) { + new Ajax.Request("/response", extendDefault({ + parameters: Fixtures.headerJson, + onComplete: function(transport, json) { + this.assertEqual('hello #éà', transport.headerJSON.test); + this.assertEqual('hello #éà', json.test); + }.bind(this) + })); + + new Ajax.Request("/response", extendDefault({ + onComplete: function(transport, json) { + this.assertNull(transport.headerJSON) + this.assertNull(json) + }.bind(this) + })); + } else { + this.info(message); + } + }, + + testGetHeader: function() { + if (this.isRunningFromRake) { + new Ajax.Request("/response", extendDefault({ + parameters: { 'X-TEST': 'some value' }, + onComplete: function(transport) { + this.assertEqual('some value', transport.getHeader('X-Test')); + this.assertNull(transport.getHeader('X-Inexistant')); + }.bind(this) + })); + } else { + this.info(message); + } + }, + + testParametersCanBeHash: function() { + if (this.isRunningFromRake) { + new Ajax.Request("/response", extendDefault({ + parameters: $H({ "one": "two", "three": "four" }), + onComplete: function(transport) { + this.assertEqual("two", transport.getHeader("one")); + this.assertEqual("four", transport.getHeader("three")); + this.assertNull(transport.getHeader("toObject")); + }.bind(this) + })); + } else { + this.info(message); + } + }, + + testIsSameOriginMethod: function() { + var isSameOrigin = Ajax.Request.prototype.isSameOrigin; + this.assert(isSameOrigin.call({ url: '/foo/bar.html' }), '/foo/bar.html'); + this.assert(isSameOrigin.call({ url: window.location.toString() }), window.location); + this.assert(!isSameOrigin.call({ url: 'http://example.com' }), 'http://example.com'); + + if (this.isRunningFromRake) { + Ajax.Request.prototype.isSameOrigin = function() { + return false + }; + + $("content").update('same origin policy'); + new Ajax.Request("/response", extendDefault({ + parameters: Fixtures.js, + onComplete: function(transport) { + this.assertEqual("same origin policy", $("content").innerHTML); + }.bind(this) + })); + + new Ajax.Request("/response", extendDefault({ + parameters: Fixtures.invalidJson, + onException: function(request, error) { + this.assert(error.message.include('Badly formed JSON string')); + }.bind(this) + })); + + new Ajax.Request("/response", extendDefault({ + parameters: { 'X-JSON': '{});window.attacked = true;({}' }, + onException: function(request, error) { + this.assert(error.message.include('Badly formed JSON string')); + }.bind(this) + })); + + Ajax.Request.prototype.isSameOrigin = isSameOrigin; + } else { + this.info(message); + } + } +}); \ No newline at end of file diff --git a/test/unit/array.html b/test/unit/array.html deleted file mode 100644 index 0b0abaf..0000000 --- a/test/unit/array.html +++ /dev/null @@ -1,219 +0,0 @@ - - - - Prototype Unit test file - - - - - - -

Prototype Unit test file

-

- Test of the Array.prototype extensions -

- - -
- -
22
- - - - - diff --git a/test/unit/array_test.js b/test/unit/array_test.js new file mode 100644 index 0000000..b172075 --- /dev/null +++ b/test/unit/array_test.js @@ -0,0 +1,189 @@ +var globalArgsTest = 'nothing to see here'; + +new Test.Unit.Runner({ + test$A: function(){ + this.assertEnumEqual([], $A({})); + }, + + testToArrayOnArguments: function(){ + function toArrayOnArguments(){ + globalArgsTest = $A(arguments); + } + toArrayOnArguments(); + this.assertEnumEqual([], globalArgsTest); + toArrayOnArguments('foo'); + this.assertEnumEqual(['foo'], globalArgsTest); + toArrayOnArguments('foo','bar'); + this.assertEnumEqual(['foo','bar'], globalArgsTest); + }, + + testToArrayOnNodeList: function(){ + // direct HTML + this.assertEqual(3, $A($('test_node').childNodes).length); + + // DOM + var element = document.createElement('div'); + element.appendChild(document.createTextNode('22')); + (2).times(function(){ element.appendChild(document.createElement('span')) }); + this.assertEqual(3, $A(element.childNodes).length); + + // HTML String + element = document.createElement('div'); + $(element).update('22 - - - Prototype Unit test file - - - - - - -

Prototype Unit test file

-

- Test of utility functions in base.js -

- - -
-
- - - - - + }); \ No newline at end of file diff --git a/test/unit/dom.html b/test/unit/dom.html deleted file mode 100644 index 42cc498..0000000 --- a/test/unit/dom.html +++ /dev/null @@ -1,1769 +0,0 @@ - - - - Prototype Unit test file - - - - - - - - -

Prototype Unit test file

-

- Test of functions in dom.js -

- - -
-

Scroll test

-
- -
- -
visible
- -
visible
- -
visible
- -
visible
- -
- -
- - - - - - - - - - - - -
Data
First Row
Second Row
-
- -
- - - - - - - - - - - - -
Data
First Row
Second Row
-
- -

Test paragraph outside of container

- -
-

Test paragraph 1 inside of container

-

Test paragraph 2 inside of container

-

Test paragraph 3 inside of container

-

Test paragraph 4 inside of container

-
- -
to be updated
-
-
-
-
-
-
-
-
-
-
- -

some text

some text

- -
V
-
H
-
S
- -
- -
- -
- - -
-
- - - - -
-

-
    -
  • -
  • -
  • -
-
-
-
- - -
- -
blah
-blah -blah - -
-
-
-
- -
test_csstext_1
-
test_csstext_2
-
test_csstext_3
-
test_csstext_4
-
test_csstext_5
- -
-
-
-
- -
- - - -
- - - - - -
- - -

- -

- - - - - -
- - - - - -
AB
C
DEF
- -
-
- -
-
- -
NFN
-
NFI
-
NFS
- -
FI
-
FS
- -op2 -op2 -op3 -op3 -
-
-
-
-
-
- - - - - - -
Data
- -
- -
- - -

-

- - -

-

content

-
-
-
-
-
-
-
-
- -

some content.

-

some content.

-

some content.

-

some content.

-
-
-
- - - -
-

- - -
-
-
-
testtest
-
XYZ
-
-
- foo - bar -
-
-
- -
-
-
-
-
-
-
-
- - - - - - - diff --git a/test/unit/dom_test.js b/test/unit/dom_test.js new file mode 100644 index 0000000..672ecf8 --- /dev/null +++ b/test/unit/dom_test.js @@ -0,0 +1,1376 @@ +var testVar = 'to be updated', testVar2 = ''; +var getInnerHTML = function(id) { + return $(id).innerHTML.toString().toLowerCase().gsub(/[\r\n\t]/, ''); +}; +var createParagraph = function(text) { + var p = document.createElement('p'); + p.appendChild(document.createTextNode(text)); + return p; +} +Element.addMethods({ + hashBrowns: function(element) { return 'hash browns'; } +}); + +Element.addMethods("LI", { + pancakes: function(element) { return "pancakes"; } +}); + +Element.addMethods("DIV", { + waffles: function(element) { return "waffles"; } +}); + +Element.addMethods($w("li div"), { + orangeJuice: function(element) { return "orange juice"; } +}); + +var documentViewportProperties; + +new Test.Unit.Runner({ + setup: function() { + if (documentViewportProperties) return; + // Based on properties check from http://www.quirksmode.org/viewport/compatibility.html + documentViewportProperties = { + properties : [ + 'self.pageXOffset', 'self.pageYOffset', + 'self.screenX', 'self.screenY', + 'self.innerHeight', 'self.innerWidth', + 'self.outerHeight', 'self.outerWidth', + 'self.screen.height', 'self.screen.width', + 'self.screen.availHeight', 'self.screen.availWidth', + 'self.screen.availTop', 'self.screen.availLeft', + 'self.screen.Top', 'self.screen.Left', + 'self.screenTop', 'self.screenLeft', + 'document.body.clientHeight', 'document.body.clientWidth', + 'document.body.scrollHeight', 'document.body.scrollWidth', + 'document.body.scrollLeft', 'document.body.scrollTop', + 'document.body.offsetHeight', 'document.body.offsetWidth', + 'document.body.offsetTop', 'document.body.offsetLeft' + ].inject([], function(properties, prop) { + if(!self.screen && prop.include('self.screen')) return; + if (!document.body && prop.include('document.body')) return; + properties.push(prop); + if (prop.include('.body') && document.documentElement) + properties.push(prop.sub('.body', '.documentElement')); + return properties; + }), + + inspect : function() { + var props = []; + this.properties.each(function(prop) { + if (eval(prop)) props[prop] = eval(prop); + }, this); + return props; + } + }; + }, + + testDollarFunction: function() { + this.assertUndefined($()); + + this.assertNull(document.getElementById('noWayThisIDExists')); + this.assertNull($('noWayThisIDExists')); + + this.assertIdentical(document.getElementById('testdiv'), $('testdiv')); + this.assertEnumEqual([ $('testdiv'), $('container') ], $('testdiv', 'container')); + this.assertEnumEqual([ $('testdiv'), undefined, $('container') ], + $('testdiv', 'noWayThisIDExists', 'container')); + var elt = $('testdiv'); + this.assertIdentical(elt, $(elt)); + this.assertRespondsTo('hide', elt); + this.assertRespondsTo('childOf', elt); + }, + + testGetElementsByClassName: function() { + if (document.getElementsByClassName.toString().include('[native code]')) { + this.info("browser uses native getElementsByClassName; skipping tests"); + return; + } + + + var div = $('class_names'), list = $('class_names_ul'); + + this.assertElementsMatch(document.getElementsByClassName('A'), 'p.A', 'ul#class_names_ul.A', 'li.A.C'); + + if (Prototype.Browser.IE) + this.assertUndefined(document.getElementById('unextended').show); + + this.assertElementsMatch(div.getElementsByClassName('B'), 'ul#class_names_ul.A.B', 'div.B.C.D'); + this.assertElementsMatch(div.getElementsByClassName('D C B'), 'div.B.C.D'); + this.assertElementsMatch(div.getElementsByClassName(' D\nC\tB '), 'div.B.C.D'); + this.assertElementsMatch(div.getElementsByClassName($w('D C B'))); + this.assertElementsMatch(list.getElementsByClassName('A'), 'li.A.C'); + this.assertElementsMatch(list.getElementsByClassName(' A '), 'li.A.C'); + this.assertElementsMatch(list.getElementsByClassName('C A'), 'li.A.C'); + this.assertElementsMatch(list.getElementsByClassName("C\nA "), 'li.A.C'); + this.assertElementsMatch(list.getElementsByClassName('B')); + this.assertElementsMatch(list.getElementsByClassName('1'), 'li.1'); + this.assertElementsMatch(list.getElementsByClassName([1]), 'li.1'); + this.assertElementsMatch(list.getElementsByClassName(['1 junk'])); + this.assertElementsMatch(list.getElementsByClassName('')); + this.assertElementsMatch(list.getElementsByClassName(' ')); + this.assertElementsMatch(list.getElementsByClassName([''])); + this.assertElementsMatch(list.getElementsByClassName([' ', ''])); + this.assertElementsMatch(list.getElementsByClassName({})); + + // those lookups shouldn't have extended all nodes in document + if (Prototype.Browser.IE) this.assertUndefined(document.getElementById('unextended')['show']); + }, + + testElementInsertWithHTML: function() { + Element.insert('insertions-main', {before:'

before text

more testing

'}); + this.assert(getInnerHTML('insertions-container').startsWith('

before text

more testing

')); + Element.insert('insertions-main', {after:'

after text

more testing

'}); + this.assert(getInnerHTML('insertions-container').endsWith('

after text

more testing

')); + Element.insert('insertions-main', {top:'

top text.

more testing

'}); + this.assert(getInnerHTML('insertions-main').startsWith('

top text.

more testing

')); + Element.insert('insertions-main', {bottom:'

bottom text.

more testing

'}); + this.assert(getInnerHTML('insertions-main').endsWith('

bottom text.

more testing

')); + }, + + testElementInsertWithDOMNode: function() { + Element.insert('insertions-node-main', {before: createParagraph('node before')}); + this.assert(getInnerHTML('insertions-node-container').startsWith('

node before

')); + Element.insert('insertions-node-main', {after: createParagraph('node after')}); + this.assert(getInnerHTML('insertions-node-container').endsWith('

node after

')); + Element.insert('insertions-node-main', {top:createParagraph('node top')}); + this.assert(getInnerHTML('insertions-node-main').startsWith('

node top

')); + Element.insert('insertions-node-main', {bottom:createParagraph('node bottom')}); + this.assert(getInnerHTML('insertions-node-main').endsWith('

node bottom

')); + this.assertEqual($('insertions-node-main'), $('insertions-node-main').insert(document.createElement('p'))); + }, + + testElementInsertWithToElementMethod: function() { + Element.insert('insertions-node-main', {toElement: createParagraph.curry('toElement') }); + this.assert(getInnerHTML('insertions-node-main').endsWith('

toelement

')); + Element.insert('insertions-node-main', {bottom: {toElement: createParagraph.curry('bottom toElement') }}); + this.assert(getInnerHTML('insertions-node-main').endsWith('

bottom toelement

')); + }, + + testElementInsertWithToHTMLMethod: function() { + Element.insert('insertions-node-main', {toHTML: function() { return '

toHTML

'} }); + this.assert(getInnerHTML('insertions-node-main').endsWith('

tohtml

')); + Element.insert('insertions-node-main', {bottom: {toHTML: function() { return '

bottom toHTML

'} }}); + this.assert(getInnerHTML('insertions-node-main').endsWith('

bottom tohtml

')); + }, + + testElementInsertWithNonString: function() { + Element.insert('insertions-main', {bottom:3}); + this.assert(getInnerHTML('insertions-main').endsWith('3')); + }, + + testElementInsertInTables: function() { + Element.insert('second_row', {after:'Third Row'}); + this.assert($('second_row').descendantOf('table')); + + $('a_cell').insert({top:'hello world'}); + this.assert($('a_cell').innerHTML.startsWith('hello world')); + $('a_cell').insert({after:'hi planet'}); + this.assertEqual('hi planet', $('a_cell').next().innerHTML); + $('table_for_insertions').insert('a cell!'); + this.assert($('table_for_insertions').innerHTML.gsub('\r\n', '').toLowerCase().include('a cell!')); + $('row_1').insert({after:'last'}); + this.assertEqual('last', $A($('table_for_row_insertions').getElementsByTagName('tr')).last().lastChild.innerHTML); + }, + + testElementInsertInSelect: function() { + var selectTop = $('select_for_insert_top'), selectBottom = $('select_for_insert_bottom'); + selectBottom.insert(''); + this.assertEqual('option 45', selectBottom.getValue()); + selectTop.insert({top:''}); + this.assertEqual(4, selectTop.options.length); + }, + + testElementMethodInsert: function() { + $('element-insertions-main').insert({before:'some text before'}); + this.assert(getInnerHTML('element-insertions-container').startsWith('some text before')); + $('element-insertions-main').insert({after:'some text after'}); + this.assert(getInnerHTML('element-insertions-container').endsWith('some text after')); + $('element-insertions-main').insert({top:'some text top'}); + this.assert(getInnerHTML('element-insertions-main').startsWith('some text top')); + $('element-insertions-main').insert({bottom:'some text bottom'}); + this.assert(getInnerHTML('element-insertions-main').endsWith('some text bottom')); + + $('element-insertions-main').insert('some more text at the bottom'); + this.assert(getInnerHTML('element-insertions-main').endsWith('some more text at the bottom')); + + $('element-insertions-main').insert({TOP:'some text uppercase top'}); + this.assert(getInnerHTML('element-insertions-main').startsWith('some text uppercase top')); + + $('element-insertions-multiple-main').insert({ + top:'1', bottom:2, before: new Element('p').update('3'), after:'4' + }); + this.assert(getInnerHTML('element-insertions-multiple-main').startsWith('1')); + this.assert(getInnerHTML('element-insertions-multiple-main').endsWith('2')); + this.assert(getInnerHTML('element-insertions-multiple-container').startsWith('

3

')); + this.assert(getInnerHTML('element-insertions-multiple-container').endsWith('4')); + + $('element-insertions-main').update('test'); + $('element-insertions-main').insert(null); + $('element-insertions-main').insert({bottom:null}); + this.assertEqual('test', getInnerHTML('element-insertions-main')); + $('element-insertions-main').insert(1337); + this.assertEqual('test1337', getInnerHTML('element-insertions-main')); + }, + + testNewElementInsert: function() { + var container = new Element('div'); + element = new Element('div'); + container.insert(element); + + element.insert({ before: '

a paragraph

' }); + this.assertEqual('

a paragraph

', getInnerHTML(container)); + element.insert({ after: 'some text' }); + this.assertEqual('

a paragraph

some text', getInnerHTML(container)); + + element.insert({ top: '

a paragraph

' }); + this.assertEqual('

a paragraph

', getInnerHTML(element)); + element.insert('some text'); + this.assertEqual('

a paragraph

some text', getInnerHTML(element)); + }, + + testInsertionBackwardsCompatibility: function() { + new Insertion.Before('element-insertions-main', 'some backward-compatibility testing before'); + this.assert(getInnerHTML('element-insertions-container').include('some backward-compatibility testing before')); + new Insertion.After('element-insertions-main', 'some backward-compatibility testing after'); + this.assert(getInnerHTML('element-insertions-container').include('some backward-compatibility testing after')); + new Insertion.Top('element-insertions-main', 'some backward-compatibility testing top'); + this.assert(getInnerHTML('element-insertions-main').startsWith('some backward-compatibility testing top')); + new Insertion.Bottom('element-insertions-main', 'some backward-compatibility testing bottom'); + this.assert(getInnerHTML('element-insertions-main').endsWith('some backward-compatibility testing bottom')); + }, + + testElementWrap: function() { + var element = $('wrap'), parent = document.createElement('div'); + element.wrap(); + this.assert(getInnerHTML('wrap-container').startsWith('
\ntestVar="hello!";\n'); + this.assertEqual('hello from div!',$('testdiv').innerHTML); + this.wait(100,function(){ + this.assertEqual('hello!',testVar); + + Element.update('testdiv','another hello from div!\n - - - - -

Prototype Unit test file

-

- Test of extra methods mixed in to elements with $() and $$(). -

- - -
- -

Test Form Elements

-
- - -
- - - - - \ No newline at end of file diff --git a/test/unit/element_mixins_test.js b/test/unit/element_mixins_test.js new file mode 100644 index 0000000..babf4a0 --- /dev/null +++ b/test/unit/element_mixins_test.js @@ -0,0 +1,35 @@ +Form.Element.Methods.coffee = Prototype.K; +Element.addMethods(); + +new Test.Unit.Runner({ + testInput: function() { + this.assert($("input").present != null); + this.assert(typeof $("input").present == 'function'); + this.assert($("input").select != null); + this.assertRespondsTo('present', Form.Element); + this.assertRespondsTo('present', Form.Element.Methods); + this.assertRespondsTo('coffee', $('input')); + this.assertIdentical(Prototype.K, Form.Element.coffee); + this.assertIdentical(Prototype.K, Form.Element.Methods.coffee); + }, + + testForm: function() { + this.assert($("form").reset != null); + this.assert($("form").getInputs().length == 2); + }, + + testEvent: function() { + this.assert($("form").observe != null) + // Can't really test this one with TestUnit... + $('form').observe("submit", function(e) { + alert("yeah!"); + Event.stop(e); + }); + }, + + testCollections: function() { + this.assert($$("input").all(function(input) { + return (input.focus != null); + })); + } +}); \ No newline at end of file diff --git a/test/unit/enumerable.html b/test/unit/enumerable.html deleted file mode 100644 index 510a691..0000000 --- a/test/unit/enumerable.html +++ /dev/null @@ -1,322 +0,0 @@ - - - - Prototype Unit test file - - - - - - -

Prototype Unit test file

-

- Test of utility functions in enumerable.js -

- - -
- - - - - - - - -
- - - - - diff --git a/test/unit/enumerable_test.js b/test/unit/enumerable_test.js new file mode 100644 index 0000000..fd05fd4 --- /dev/null +++ b/test/unit/enumerable_test.js @@ -0,0 +1,287 @@ +var Fixtures = { + People: [ + {name: 'Sam Stephenson', nickname: 'sam-'}, + {name: 'Marcel Molina Jr.', nickname: 'noradio'}, + {name: 'Scott Barron', nickname: 'htonl'}, + {name: 'Nicholas Seckar', nickname: 'Ulysses'} + ], + + Nicknames: $w('sam- noradio htonl Ulysses'), + + Basic: [1, 2, 3], + + Primes: [ + 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, + 71, 73, 79, 83, 89, 97 + ], + + Z: [] +}; + +for (var i = 1; i <= 100; i++) + Fixtures.Z.push(i); + +function prime(value) { + for (var i = 2; i < value; i++) + if (value % i == 0) return false; + return true; +} + +new Test.Unit.Runner({ + testEachBreak: function() { + var result = 0; + Fixtures.Basic.each(function(value) { + if ((result = value) == 2) throw $break; + }); + + this.assertEqual(2, result); + }, + + testEachReturnActsAsContinue: function() { + var results = []; + Fixtures.Basic.each(function(value) { + if (value == 2) return; + results.push(value); + }); + + this.assertEqual('1, 3', results.join(', ')); + }, + + testEachChaining: function() { + this.assertEqual(Fixtures.Primes, Fixtures.Primes.each(Prototype.emptyFunction)); + this.assertEqual(3, Fixtures.Basic.each(Prototype.emptyFunction).length); + }, + + testEnumContext: function() { + var results = []; + Fixtures.Basic.each(function(value) { + results.push(value * this.i); + }, { i: 2 }); + + this.assertEqual('2 4 6', results.join(' ')); + + this.assert(Fixtures.Basic.all(function(value){ + return value >= this.min && value <= this.max; + }, { min: 1, max: 3 })); + this.assert(!Fixtures.Basic.all(function(value){ + return value >= this.min && value <= this.max; + })); + this.assert(Fixtures.Basic.any(function(value){ + return value == this.target_value; + }, { target_value: 2 })); + }, + + testAny: function() { + this.assert(!([].any())); + + this.assert([true, true, true].any()); + this.assert([true, false, false].any()); + this.assert(![false, false, false].any()); + + this.assert(Fixtures.Basic.any(function(value) { + return value > 2; + })); + this.assert(!Fixtures.Basic.any(function(value) { + return value > 5; + })); + }, + + testAll: function() { + this.assert([].all()); + + this.assert([true, true, true].all()); + this.assert(![true, false, false].all()); + this.assert(![false, false, false].all()); + + this.assert(Fixtures.Basic.all(function(value) { + return value > 0; + })); + this.assert(!Fixtures.Basic.all(function(value) { + return value > 1; + })); + }, + + testCollect: function() { + this.assertEqual(Fixtures.Nicknames.join(', '), + Fixtures.People.collect(function(person) { + return person.nickname; + }).join(", ")); + + this.assertEqual(26, Fixtures.Primes.map().length); + }, + + testDetect: function() { + this.assertEqual('Marcel Molina Jr.', + Fixtures.People.detect(function(person) { + return person.nickname.match(/no/); + }).name); + }, + + testEachSlice: function() { + this.assertEnumEqual([], [].eachSlice(2)); + this.assertEqual(1, [1].eachSlice(1).length); + this.assertEnumEqual([1], [1].eachSlice(1)[0]); + this.assertEqual(2, Fixtures.Basic.eachSlice(2).length); + this.assertEnumEqual( + [3, 2, 1, 11, 7, 5, 19, 17, 13, 31, 29, 23, 43, 41, 37, 59, 53, 47, 71, 67, 61, 83, 79, 73, 97, 89], + Fixtures.Primes.eachSlice( 3, function(slice){ return slice.reverse() }).flatten() + ); + this.assertEnumEqual(Fixtures.Basic, Fixtures.Basic.eachSlice(-10)); + this.assertEnumEqual(Fixtures.Basic, Fixtures.Basic.eachSlice(0)); + this.assertNotIdentical(Fixtures.Basic, Fixtures.Basic.eachSlice(0)); + }, + + testEachWithIndex: function() { + var nicknames = [], indexes = []; + Fixtures.People.each(function(person, index) { + nicknames.push(person.nickname); + indexes.push(index); + }); + + this.assertEqual(Fixtures.Nicknames.join(', '), + nicknames.join(', ')); + this.assertEqual('0, 1, 2, 3', indexes.join(', ')); + }, + + testFindAll: function() { + this.assertEqual(Fixtures.Primes.join(', '), + Fixtures.Z.findAll(prime).join(', ')); + }, + + testGrep: function() { + this.assertEqual('noradio, htonl', + Fixtures.Nicknames.grep(/o/).join(", ")); + + this.assertEqual('NORADIO, HTONL', + Fixtures.Nicknames.grep(/o/, function(nickname) { + return nickname.toUpperCase(); + }).join(", ")) + + this.assertEnumEqual($('grepHeader', 'grepCell'), + $('grepTable', 'grepTBody', 'grepRow', 'grepHeader', 'grepCell').grep(new Selector('.cell'))); + }, + + testInclude: function() { + this.assert(Fixtures.Nicknames.include('sam-')); + this.assert(Fixtures.Nicknames.include('noradio')); + this.assert(!Fixtures.Nicknames.include('gmosx')); + this.assert(Fixtures.Basic.include(2)); + this.assert(Fixtures.Basic.include('2')); + this.assert(!Fixtures.Basic.include('4')); + }, + + testInGroupsOf: function() { + this.assertEnumEqual([], [].inGroupsOf(3)); + + var arr = [1, 2, 3, 4, 5, 6].inGroupsOf(3); + this.assertEqual(2, arr.length); + this.assertEnumEqual([1, 2, 3], arr[0]); + this.assertEnumEqual([4, 5, 6], arr[1]); + + arr = [1, 2, 3, 4, 5, 6].inGroupsOf(4); + this.assertEqual(2, arr.length); + this.assertEnumEqual([1, 2, 3, 4], arr[0]); + this.assertEnumEqual([5, 6, null, null], arr[1]); + + var basic = Fixtures.Basic + + arr = basic.inGroupsOf(4,'x'); + this.assertEqual(1, arr.length); + this.assertEnumEqual([1, 2, 3, 'x'], arr[0]); + + this.assertEnumEqual([1,2,3,'a'], basic.inGroupsOf(2, 'a').flatten()); + + arr = basic.inGroupsOf(5, ''); + this.assertEqual(1, arr.length); + this.assertEnumEqual([1, 2, 3, '', ''], arr[0]); + + this.assertEnumEqual([1,2,3,0], basic.inGroupsOf(2, 0).flatten()); + this.assertEnumEqual([1,2,3,false], basic.inGroupsOf(2, false).flatten()); + }, + + testInject: function() { + this.assertEqual(1061, + Fixtures.Primes.inject(0, function(sum, value) { + return sum + value; + })); + }, + + testInvoke: function() { + var result = [[2, 1, 3], [6, 5, 4]].invoke('sort'); + this.assertEqual(2, result.length); + this.assertEqual('1, 2, 3', result[0].join(', ')); + this.assertEqual('4, 5, 6', result[1].join(', ')); + + result = result.invoke('invoke', 'toString', 2); + this.assertEqual('1, 10, 11', result[0].join(', ')); + this.assertEqual('100, 101, 110', result[1].join(', ')); + }, + + testMax: function() { + this.assertEqual(100, Fixtures.Z.max()); + this.assertEqual(97, Fixtures.Primes.max()); + this.assertEqual(2, [ -9, -8, -7, -6, -4, -3, -2, 0, -1, 2 ].max()); + this.assertEqual('sam-', Fixtures.Nicknames.max()); // ?s > ?U + }, + + testMin: function() { + this.assertEqual(1, Fixtures.Z.min()); + this.assertEqual(0, [ 1, 2, 3, 4, 5, 6, 7, 8, 0, 9 ].min()); + this.assertEqual('Ulysses', Fixtures.Nicknames.min()); // ?U < ?h + }, + + testPartition: function() { + var result = Fixtures.People.partition(function(person) { + return person.name.length < 15; + }).invoke('pluck', 'nickname'); + + this.assertEqual(2, result.length); + this.assertEqual('sam-, htonl', result[0].join(', ')); + this.assertEqual('noradio, Ulysses', result[1].join(', ')); + }, + + testPluck: function() { + this.assertEqual(Fixtures.Nicknames.join(', '), + Fixtures.People.pluck('nickname').join(', ')); + }, + + testReject: function() { + this.assertEqual(0, + Fixtures.Nicknames.reject(Prototype.K).length); + + this.assertEqual('sam-, noradio, htonl', + Fixtures.Nicknames.reject(function(nickname) { + return nickname != nickname.toLowerCase(); + }).join(', ')); + }, + + testSortBy: function() { + this.assertEqual('htonl, noradio, sam-, Ulysses', + Fixtures.People.sortBy(function(value) { + return value.nickname.toLowerCase(); + }).pluck('nickname').join(', ')); + }, + + testToArray: function() { + var result = Fixtures.People.toArray(); + this.assert(result != Fixtures.People); // they're different objects... + this.assertEqual(Fixtures.Nicknames.join(', '), + result.pluck('nickname').join(', ')); // but the values are the same + }, + + testZip: function() { + var result = [1, 2, 3].zip([4, 5, 6], [7, 8, 9]); + this.assertEqual('[[1, 4, 7], [2, 5, 8], [3, 6, 9]]', result.inspect()); + + result = [1, 2, 3].zip([4, 5, 6], [7, 8, 9], function(array) { return array.reverse() }); + this.assertEqual('[[7, 4, 1], [8, 5, 2], [9, 6, 3]]', result.inspect()); + }, + + testSize: function() { + this.assertEqual(4, Fixtures.People.size()); + this.assertEqual(4, Fixtures.Nicknames.size()); + this.assertEqual(26, Fixtures.Primes.size()); + this.assertEqual(0, [].size()); + } +}); \ No newline at end of file diff --git a/test/unit/event.html b/test/unit/event.html deleted file mode 100644 index 1e35ce7..0000000 --- a/test/unit/event.html +++ /dev/null @@ -1,268 +0,0 @@ - - - - Prototype Unit test file - - - - - - -

Prototype Unit test file

-

- Test of event handling code in event.js -

- - -
- - -
- - - - - - diff --git a/test/unit/event_test.js b/test/unit/event_test.js new file mode 100644 index 0000000..a0ab793 --- /dev/null +++ b/test/unit/event_test.js @@ -0,0 +1,231 @@ +var documentLoaded = document.loaded; + +new Test.Unit.Runner({ + + // test firing an event and observing it on the element it's fired from + testCustomEventFiring: function() { + var span = $("span"), fired = false, observer = function(event) { + this.assertEqual(span, event.element()); + this.assertEqual(1, event.memo.index); + fired = true; + }.bind(this); + + span.observe("test:somethingHappened", observer); + span.fire("test:somethingHappened", { index: 1 }); + this.assert(fired); + + fired = false; + span.fire("test:somethingElseHappened"); + this.assert(!fired); + + span.stopObserving("test:somethingHappened", observer); + span.fire("test:somethingHappened"); + this.assert(!fired); + }, + + // test firing an event and observing it on a containing element + testCustomEventBubbling: function() { + var span = $("span"), outer = $("outer"), fired = false, observer = function(event) { + this.assertEqual(span, event.element()); + fired = true; + }.bind(this); + + outer.observe("test:somethingHappened", observer); + span.fire("test:somethingHappened"); + this.assert(fired); + + fired = false; + span.fire("test:somethingElseHappened"); + this.assert(!fired); + + outer.stopObserving("test:somethingHappened", observer); + span.fire("test:somethingHappened"); + this.assert(!fired); + }, + + testCustomEventCanceling: function() { + var span = $("span"), outer = $("outer"), inner = $("inner"); + var fired = false, stopped = false; + + function outerObserver(event) { + fired = span == event.element(); + } + + function innerObserver(event) { + event.stop(); + stopped = true; + } + + inner.observe("test:somethingHappened", innerObserver); + outer.observe("test:somethingHappened", outerObserver); + span.fire("test:somethingHappened"); + this.assert(stopped); + this.assert(!fired); + + fired = stopped = false; + inner.stopObserving("test:somethingHappened", innerObserver); + span.fire("test:somethingHappened"); + this.assert(!stopped); + this.assert(fired); + + outer.stopObserving("test:somethingHappened", outerObserver); + }, + + testEventObjectIsExtended: function() { + var span = $("span"), event, observedEvent, observer = function(e) { observedEvent = e }; + span.observe("test:somethingHappened", observer); + event = span.fire("test:somethingHappened"); + this.assertEqual(event, observedEvent); + this.assertEqual(Event.Methods.stop.methodize(), event.stop); + span.stopObserving("test:somethingHappened", observer); + + event = span.fire("test:somethingHappenedButNoOneIsListening"); + this.assertEqual(Event.Methods.stop.methodize(), event.stop); + }, + + testEventObserversAreBoundToTheObservedElement: function() { + var span = $("span"), target, observer = function() { target = this }; + + span.observe("test:somethingHappened", observer); + span.fire("test:somethingHappened"); + span.stopObserving("test:somethingHappened", observer); + this.assertEqual(span, target); + target = null; + + var outer = $("outer"); + outer.observe("test:somethingHappened", observer); + span.fire("test:somethingHappened"); + outer.stopObserving("test:somethingHappened", observer); + this.assertEqual(outer, target); + }, + + testMultipleCustomEventObserversWithTheSameHandler: function() { + var span = $("span"), count = 0, observer = function() { count++ }; + + span.observe("test:somethingHappened", observer); + span.observe("test:somethingElseHappened", observer); + span.fire("test:somethingHappened"); + this.assertEqual(1, count); + span.fire("test:somethingElseHappened"); + this.assertEqual(2, count); + }, + + testStopObservingWithoutArguments: function() { + var span = $("span"), count = 0, observer = function() { count++ }; + + span.observe("test:somethingHappened", observer); + span.observe("test:somethingElseHappened", observer); + span.stopObserving(); + span.fire("test:somethingHappened"); + this.assertEqual(0, count); + span.fire("test:somethingElseHappened"); + this.assertEqual(0, count); + }, + + testStopObservingWithoutHandlerArgument: function() { + var span = $("span"), count = 0, observer = function() { count++ }; + + span.observe("test:somethingHappened", observer); + span.observe("test:somethingElseHappened", observer); + span.stopObserving("test:somethingHappened"); + span.fire("test:somethingHappened"); + this.assertEqual(0, count); + span.fire("test:somethingElseHappened"); + this.assertEqual(1, count); + span.stopObserving("test:somethingElseHappened"); + span.fire("test:somethingElseHappened"); + this.assertEqual(1, count); + }, + + testStopObservingRemovesHandlerFromCache: function() { + var span = $("span"), observer = function() { }, eventID; + + span.observe("test:somethingHappened", observer); + eventID = span._prototypeEventID; + + this.assert(Event.cache[eventID]); + this.assert(Object.isArray(Event.cache[eventID]["test:somethingHappened"])); + this.assertEqual(1, Event.cache[eventID]["test:somethingHappened"].length); + + span.stopObserving("test:somethingHappened", observer); + this.assert(Event.cache[eventID]); + this.assert(Object.isArray(Event.cache[eventID]["test:somethingHappened"])); + this.assertEqual(0, Event.cache[eventID]["test:somethingHappened"].length); + }, + + testObserveAndStopObservingAreChainable: function() { + var span = $("span"), observer = function() { }; + + this.assertEqual(span, span.observe("test:somethingHappened", observer)); + this.assertEqual(span, span.stopObserving("test:somethingHappened", observer)); + + span.observe("test:somethingHappened", observer); + this.assertEqual(span, span.stopObserving("test:somethingHappened")); + + span.observe("test:somethingHappened", observer); + this.assertEqual(span, span.stopObserving()); + this.assertEqual(span, span.stopObserving()); // assert it again, after there are no observers + + span.observe("test:somethingHappened", observer); + this.assertEqual(span, span.observe("test:somethingHappened", observer)); // try to reuse the same observer + span.stopObserving(); + }, + + testDocumentLoaded: function() { + this.assert(!documentLoaded); + this.assert(document.loaded); + }, + + testDocumentContentLoadedEventFiresBeforeWindowLoad: function() { + this.assert(eventResults.contentLoaded, "contentLoaded"); + this.assert(eventResults.contentLoaded.endOfDocument, "contentLoaded.endOfDocument"); + this.assert(!eventResults.contentLoaded.windowLoad, "!contentLoaded.windowLoad"); + this.assert(eventResults.windowLoad, "windowLoad"); + this.assert(eventResults.windowLoad.endOfDocument, "windowLoad.endOfDocument"); + this.assert(eventResults.windowLoad.contentLoaded, "windowLoad.contentLoaded"); + }, + + testEventStopped: function() { + var span = $("span"), event; + + span.observe("test:somethingHappened", function() { }); + event = span.fire("test:somethingHappened"); + this.assert(!event.stopped, "event.stopped should be false with an empty observer"); + span.stopObserving("test:somethingHappened"); + + span.observe("test:somethingHappened", function(e) { e.stop() }); + event = span.fire("test:somethingHappened"); + this.assert(event.stopped, "event.stopped should be true for an observer that calls stop"); + span.stopObserving("test:somethingHappened"); + }, + + testEventFindElement: function() { + var span = $("span"), event; + event = span.fire("test:somethingHappened"); + this.assertElementMatches(event.findElement(), 'span#span'); + this.assertElementMatches(event.findElement('span'), 'span#span'); + this.assertElementMatches(event.findElement('p'), 'p#inner'); + this.assertEqual(null, event.findElement('div.does_not_exist')); + this.assertElementMatches(event.findElement('.does_not_exist, span'), 'span#span'); + }, + + testEventIDDuplication: function() { + $('container').down().observe("test:somethingHappened", Prototype.emptyFunction); + $('container').innerHTML += $('container').innerHTML; + this.assertUndefined($('container').down(1)._prototypeEventID); + } +}); + +document.observe("dom:loaded", function(event) { + eventResults.contentLoaded = { + endOfDocument: eventResults.endOfDocument, + windowLoad: eventResults.windowLoad + }; +}); + +Event.observe(window, "load", function(event) { + eventResults.windowLoad = { + endOfDocument: eventResults.endOfDocument, + contentLoaded: eventResults.contentLoaded + }; +}); diff --git a/test/unit/fixtures/ajax.html b/test/unit/fixtures/ajax.html new file mode 100644 index 0000000..4af5e26 --- /dev/null +++ b/test/unit/fixtures/ajax.html @@ -0,0 +1,2 @@ +
+
diff --git a/test/unit/fixtures/array.html b/test/unit/fixtures/array.html new file mode 100644 index 0000000..8f09187 --- /dev/null +++ b/test/unit/fixtures/array.html @@ -0,0 +1 @@ +
22
diff --git a/test/unit/fixtures/base.html b/test/unit/fixtures/base.html new file mode 100644 index 0000000..5a08fbd --- /dev/null +++ b/test/unit/fixtures/base.html @@ -0,0 +1,6 @@ +
+
    +
  • +
  • +
  • +
\ No newline at end of file diff --git a/test/unit/fixtures/dom.html b/test/unit/fixtures/dom.html new file mode 100644 index 0000000..b296502 --- /dev/null +++ b/test/unit/fixtures/dom.html @@ -0,0 +1,366 @@ + + +
+

Scroll test

+
+ +
visible
+ +
visible
+ +
visible
+ +
visible
+ +
+ +
+ + + + + + + + + + + + +
Data
First Row
Second Row
+
+ +
+ + + + + + + + + + + + +
Data
First Row
Second Row
+
+ +

Test paragraph outside of container

+ +
+

Test paragraph 1 inside of container

+

Test paragraph 2 inside of container

+

Test paragraph 3 inside of container

+

Test paragraph 4 inside of container

+
+ +
to be updated
+
+
+
+
+
+
+
+
+
+
+ +

some text

some text

+ +
V
+
H
+
S
+ +
+ +
+ +
+ + +
+
+ + + + +
+

+
    +
  • +
  • +
  • +
+
+
+
+ + +
+ +
blah
+blah +blah + +
+
+
+
+ +
test_csstext_1
+
test_csstext_2
+
test_csstext_3
+
test_csstext_4
+
test_csstext_5
+ +
+
+
+
+ +
+ + + +
+ + + + + +
+ + +

+ +

+ + + + + +
+ + + + + +
AB
C
DEF
+ +
+
+ +
+
+ +
NFN
+
NFI
+
NFS
+ +
FI
+
FS
+ +op2 +op2 +op3 +op3 +
+
+
+
+
+
+ + + + + + +
Data
+ +
+ +
+ + +

+

+ + +

+

content

+
+
+
+
+
+
+
+
+ +

some content.

+

some content.

+

some content.

+

some content.

+
+
+
+ + + +
+

+ + +
+
+
+
testtest
+
XYZ
+
+
+ foo + bar +
+
+
+ +
+
+
+
+
+
+
+
+ + \ No newline at end of file diff --git a/test/unit/fixtures/element_mixins.html b/test/unit/fixtures/element_mixins.html new file mode 100644 index 0000000..583d0e5 --- /dev/null +++ b/test/unit/fixtures/element_mixins.html @@ -0,0 +1,4 @@ +
+ + +
\ No newline at end of file diff --git a/test/unit/fixtures/enumerable.html b/test/unit/fixtures/enumerable.html new file mode 100644 index 0000000..5e7e8f3 --- /dev/null +++ b/test/unit/fixtures/enumerable.html @@ -0,0 +1,8 @@ + + + + + + + +
diff --git a/test/unit/fixtures/event.html b/test/unit/fixtures/event.html new file mode 100644 index 0000000..baa88a7 --- /dev/null +++ b/test/unit/fixtures/event.html @@ -0,0 +1,4 @@ + +
diff --git a/test/unit/fixtures/form.html b/test/unit/fixtures/form.html new file mode 100644 index 0000000..2259395 --- /dev/null +++ b/test/unit/fixtures/form.html @@ -0,0 +1,104 @@ +
+ +
This is not a form element
+ + + + +
+ +
+
+ + + + + +
+ + +
+ + + + + +
+ + +
+ + + + +
+ + + +
+
+ +
+ + + + + +
This is not a form element
+ + + +
+
+ + + + +
+
+

+ + +
+ +
+

+ + + +
+ +
+

+ + + +
+ +
diff --git a/test/unit/fixtures/position.html b/test/unit/fixtures/position.html new file mode 100644 index 0000000..5fd7bdf --- /dev/null +++ b/test/unit/fixtures/position.html @@ -0,0 +1,9 @@ +
+ +
+
+
+
testtest
+
+
+
diff --git a/test/unit/fixtures/selector.html b/test/unit/fixtures/selector.html new file mode 100644 index 0000000..d745c8f --- /dev/null +++ b/test/unit/fixtures/selector.html @@ -0,0 +1,69 @@ + diff --git a/test/unit/fixtures/unittest.html b/test/unit/fixtures/unittest.html new file mode 100644 index 0000000..15d303a --- /dev/null +++ b/test/unit/fixtures/unittest.html @@ -0,0 +1,18 @@ +
+ + +
+ +
+ + + +
+
+ +
  • x1
  • x2
+
  • x1
  • x2
+ +
XXXX
+ +
testcss1
testcss1
diff --git a/test/unit/form.html b/test/unit/form.html deleted file mode 100644 index 082682b..0000000 --- a/test/unit/form.html +++ /dev/null @@ -1,489 +0,0 @@ - - - - Prototype Unit test file - - - - - - -

Prototype Unit test file

-

- Test of utility functions in form.js -

- - -
- -
- -
This is not a form element
- - - - -
- -
-
- - - - - -
- - -
- - - - - -
- - -
- - - - -
- - - -
-
- -
- - - - - -
This is not a form element
- - - -
-
- - - - -
-
-

- - -
- -
-

- - - -
- -
-

- - - -
- -
- - - - - diff --git a/test/unit/form_test.js b/test/unit/form_test.js new file mode 100644 index 0000000..ff4b5c9 --- /dev/null +++ b/test/unit/form_test.js @@ -0,0 +1,357 @@ +// sweet sweet additional assertions +Object.extend(Test.Unit.Testcase.prototype, { + assertEnabled: function() { + for (var i = 0, element; element = arguments[i]; i++) { + this.assert(!$(element).disabled, Test.Unit.inspect(element) + ' was disabled'); + } + }, + assertDisabled: function() { + for (var i = 0, element; element = arguments[i]; i++) { + this.assert($(element).disabled, Test.Unit.inspect(element) + ' was enabled'); + } + } +}); + +new Test.Unit.Runner({ + + // Make sure to set defaults in the test forms, as some browsers override this + // with previously entered values on page reload + setup: function(){ + $$('form').each(function(f){ f.reset() }); + // hidden value does not reset (for some reason) + $('bigform')['tf_hidden'].value = ''; + }, + + testDollarF: function(){ + this.assertEqual("4", $F("input_enabled")); + }, + + testFormElementEventObserver: function(){ + var callbackCounter = 0; + var observer = new Form.Element.EventObserver('input_enabled', function(){ + callbackCounter++; + }); + + this.assertEqual(0, callbackCounter); + $('input_enabled').value = 'boo!'; + observer.onElementEvent(); // can't test the event directly, simulating + this.assertEqual(1, callbackCounter); + }, + + testFormElementObserver: function(){ + var timedCounter = 0; + // First part: regular field + var observer = new Form.Element.Observer('input_enabled', 0.5, function() { + ++timedCounter; + }); + + // Test it's unchanged yet + this.assertEqual(0, timedCounter); + // Test it doesn't change on first check + this.wait(550, function() { + this.assertEqual(0, timedCounter); + // Change, test it doesn't immediately change + $('input_enabled').value = 'yowza!'; + this.assertEqual(0, timedCounter); + // Test it changes on next check, but not again on the next + this.wait(550, function() { + this.assertEqual(1, timedCounter); + this.wait(550, function() { + this.assertEqual(1, timedCounter); + observer.stop(); + }); + }); + }); + + // Second part: multiple-select + [1, 2, 3].each(function(index) { + $('multiSel1_opt' + index).selected = (1 == index); + }); + timedCounter = 0; + observer = new Form.Element.Observer('multiSel1', 0.5, function() { + ++timedCounter; + }); + + // Test it's unchanged yet + this.assertEqual(0, timedCounter); + // Test it doesn't change on first check + this.wait(550, function() { + this.assertEqual(0, timedCounter); + // Change, test it doesn't immediately change + // NOTE: it is important that the 3rd be re-selected, for the + // serialize form to obtain the expected value :-) + $('multiSel1_opt3').selected = true; + this.assertEqual(0, timedCounter); + // Test it changes on next check, but not again on the next + this.wait(550, function() { + this.assertEqual(1, timedCounter); + this.wait(550, function() { + this.assertEqual(1, timedCounter); + observer.stop(); + }); + }); + }); + }, + + testFormObserver: function(){ + var timedCounter = 0; + // should work the same way was Form.Element.Observer + var observer = new Form.Observer('form', 0.5, function(form, value) { + ++timedCounter; + }); + + // Test it's unchanged yet + this.assertEqual(0, timedCounter); + // Test it doesn't change on first check + this.wait(550, function() { + this.assertEqual(0, timedCounter); + // Change, test it doesn't immediately change + $('input_enabled').value = 'yowza!'; + this.assertEqual(0, timedCounter); + // Test it changes on next check, but not again on the next + this.wait(550, function() { + this.assertEqual(1, timedCounter); + this.wait(550, function() { + this.assertEqual(1, timedCounter); + observer.stop(); + }); + }); + }); + }, + + testFormEnabling: function(){ + var form = $('bigform') + var input1 = $('dummy_disabled'); + var input2 = $('focus_text'); + + this.assertDisabled(input1); + this.assertEnabled(input2); + + form.disable(); + this.assertDisabled(input1, input2); + form.enable(); + this.assertEnabled(input1, input2); + input1.disable(); + this.assertDisabled(input1); + + // non-form elements: + var fieldset = $('selects_fieldset'); + var fields = fieldset.immediateDescendants(); + fields.each(function(select) { this.assertEnabled(select) }, this); + + Form.disable(fieldset) + fields.each(function(select) { this.assertDisabled(select) }, this); + + Form.enable(fieldset) + fields.each(function(select) { this.assertEnabled(select) }, this); + }, + + testFormElementEnabling: function(){ + var field = $('input_disabled'); + field.enable(); + this.assertEnabled(field); + field.disable(); + this.assertDisabled(field); + + var field = $('input_enabled'); + this.assertEnabled(field); + field.disable(); + this.assertDisabled(field); + field.enable(); + this.assertEnabled(field); + }, + + // due to the lack of a DOM hasFocus() API method, + // we're simulating things here a little bit + testFormActivating: function(){ + // Firefox, IE, and Safari 2+ + function getSelection(element){ + try { + if (typeof element.selectionStart == 'number') { + return element.value.substring(element.selectionStart, element.selectionEnd); + } else if (document.selection && document.selection.createRange) { + return document.selection.createRange().text; + } + } + catch(e){ return null } + } + + // Form.focusFirstElement shouldn't focus disabled elements + var element = Form.findFirstElement('bigform'); + this.assertEqual('submit', element.id); + + // Test IE doesn't select text on buttons + Form.focusFirstElement('bigform'); + if(document.selection) this.assertEqual('', getSelection(element)); + + // Form.Element.activate shouldn't select text on buttons + element = $('focus_text'); + this.assertEqual('', getSelection(element)); + + // Form.Element.activate should select text on text input elements + element.activate(); + this.assertEqual('Hello', getSelection(element)); + + // Form.Element.activate shouldn't raise an exception when the form or field is hidden + this.assertNothingRaised(function() { + $('form_focus_hidden').focusFirstElement(); + }); + }, + + testFormGetElements: function() { + var elements = Form.getElements('various'), + names = $w('tf_selectOne tf_textarea tf_checkbox tf_selectMany tf_text tf_radio tf_hidden tf_password'); + this.assertEnumEqual(names, elements.pluck('name')) + }, + + testFormGetInputs: function() { + var form = $('form'); + [form.getInputs(), Form.getInputs(form)].each(function(inputs){ + this.assertEqual(inputs.length, 5); + this.assert(inputs instanceof Array); + this.assert(inputs.all(function(input) { return (input.tagName == "INPUT"); })); + }, this); + }, + + testFormFindFirstElement: function() { + this.assertEqual($('ffe_checkbox'), $('ffe').findFirstElement()); + this.assertEqual($('ffe_ti_submit'), $('ffe_ti').findFirstElement()); + this.assertEqual($('ffe_ti2_checkbox'), $('ffe_ti2').findFirstElement()); + }, + + testFormSerialize: function() { + // form is initially empty + var form = $('bigform'); + var expected = { tf_selectOne:'', tf_textarea:'', tf_text:'', tf_hidden:'', tf_password:'' }; + this.assertHashEqual(expected, Form.serialize('various', true)); + + // set up some stuff + form['tf_selectOne'].selectedIndex = 1; + form['tf_textarea'].value = "boo hoo!"; + form['tf_text'].value = "123öäü"; + form['tf_hidden'].value = "moo%hoo&test"; + form['tf_password'].value = 'sekrit code'; + form['tf_checkbox'].checked = true; + form['tf_radio'].checked = true; + var expected = { tf_selectOne:1, tf_textarea:"boo hoo!", tf_text:"123öäü", + tf_hidden:"moo%hoo&test", tf_password:'sekrit code', tf_checkbox:'on', tf_radio:'on' } + + // return params + this.assertHashEqual(expected, Form.serialize('various', true)); + // return string + this.assertEnumEqual(Object.toQueryString(expected).split('&').sort(), + Form.serialize('various').split('&').sort()); + this.assertEqual('string', typeof $('form').serialize({ hash:false })); + + // Checks that disabled element is not included in serialized form. + $('input_enabled').enable(); + this.assertHashEqual({ val1:4, action:'blah', first_submit:'Commit it!' }, + $('form').serialize(true)); + + // should not eat empty values for duplicate names + $('checkbox_hack').checked = false; + var data = Form.serialize('value_checks', true); + this.assertEnumEqual(['', 'siamese'], data['twin']); + this.assertEqual('0', data['checky']); + + $('checkbox_hack').checked = true; + this.assertEnumEqual($w('1 0'), Form.serialize('value_checks', true)['checky']); + + // all kinds of SELECT controls + var params = Form.serialize('selects_fieldset', true); + var expected = { 'nvm[]':['One', 'Three'], evu:'', 'evm[]':['', 'Three'] }; + this.assertHashEqual(expected, params); + params = Form.serialize('selects_wrapper', true); + this.assertHashEqual(Object.extend(expected, { vu:1, 'vm[]':[1, 3], nvu:'One' }), params); + + // explicit submit button + this.assertHashEqual({ val1:4, action:'blah', second_submit:'Delete it!' }, + $('form').serialize({ submit: 'second_submit' })); + this.assertHashEqual({ val1:4, action:'blah' }, + $('form').serialize({ submit: false })); + this.assertHashEqual({ val1:4, action:'blah' }, + $('form').serialize({ submit: 'inexistent' })); + + }, + + testFormMethodsOnExtendedElements: function() { + var form = $('form'); + this.assertEqual(Form.serialize('form'), form.serialize()); + this.assertEqual(Form.Element.serialize('input_enabled'), $('input_enabled').serialize()); + this.assertNotEqual(form.serialize, $('input_enabled').serialize); + + Element.addMethods('INPUT', { anInputMethod: function(input) { return 'input' } }); + Element.addMethods('SELECT', { aSelectMethod: function(select) { return 'select' } }); + + form = $('bigform'); + var input = form['tf_text'], select = form['tf_selectOne']; + input._extendedByPrototype = select._extendedByPrototype = false; + + this.assert($(input).anInputMethod); + this.assert(!input.aSelectMethod); + this.assertEqual('input', input.anInputMethod()); + + this.assert($(select).aSelectMethod); + this.assert(!select.anInputMethod); + this.assertEqual('select', select.aSelectMethod()); + }, + + testFormRequest: function() { + request = $("form").request(); + this.assert($("form").hasAttribute("method")); + this.assert(request.url.include("fixtures/empty.js?val1=4")); + this.assertEqual("get", request.method); + + request = $("form").request({ method: "put", parameters: {val2: "hello"} }); + this.assert(request.url.endsWith("fixtures/empty.js")); + this.assertEqual(4, request.options.parameters['val1']); + this.assertEqual('hello', request.options.parameters['val2']); + this.assertEqual("post", request.method); + this.assertEqual("put", request.parameters['_method']); + + // with empty action attribute + request = $("ffe").request({ method: 'post' }); + this.assert(request.url.include("unit/tmp/form_test.html"), + 'wrong default action for form element with empty action attribute'); + }, + + testFormElementMethodsChaining: function(){ + var methods = $w('clear activate disable enable'), + formElements = $('form').getElements(); + methods.each(function(method){ + formElements.each(function(element){ + var returned = element[method](); + this.assertIdentical(element, returned); + }, this); + }, this); + }, + + testSetValue: function(){ + // text input + var input = $('input_enabled'), oldValue = input.getValue(); + this.assertEqual(input, input.setValue('foo'), 'setValue chaining is broken'); + this.assertEqual('foo', input.getValue(), 'value improperly set'); + input.setValue(oldValue); + this.assertEqual(oldValue, input.getValue(), 'value improperly restored to original'); + + // checkbox + input = $('checkbox_hack'); + input.setValue(false); + this.assertEqual(null, input.getValue(), 'checkbox should be unchecked'); + input.setValue(true); + this.assertEqual("1", input.getValue(), 'checkbox should be checked'); + // selectbox + input = $('bigform')['vu']; + input.setValue('3'); + this.assertEqual('3', input.getValue(), 'single select option improperly set'); + input.setValue('1'); + this.assertEqual('1', input.getValue()); + // multiple select + input = $('bigform')['vm[]']; + input.setValue(['2', '3']); + this.assertEnumEqual(['2', '3'], input.getValue(), + 'multiple select options improperly set'); + input.setValue(['1', '3']); + this.assertEnumEqual(['1', '3'], input.getValue()); + } +}); \ No newline at end of file diff --git a/test/unit/hash.html b/test/unit/hash.html deleted file mode 100644 index 08ee58b..0000000 --- a/test/unit/hash.html +++ /dev/null @@ -1,228 +0,0 @@ - - - - Prototype Unit test file - - - - - - -

Prototype Unit test file

-

- Test of the Hash.prototype extensions -

- - -
- - - - - diff --git a/test/unit/hash_test.js b/test/unit/hash_test.js new file mode 100644 index 0000000..ab7ad22 --- /dev/null +++ b/test/unit/hash_test.js @@ -0,0 +1,201 @@ +var Fixtures = { + one: { a: 'A#' }, + + many: { + a: 'A', + b: 'B', + c: 'C', + d: 'D#' + }, + + functions: { + quad: function(n) { return n*n }, + plus: function(n) { return n+n } + }, + + multiple: { color: $w('r g b') }, + multiple_nil: { color: ['r', null, 'g', undefined, 0] }, + multiple_all_nil: { color: [null, undefined] }, + multiple_empty: { color: [] }, + multiple_special: { 'stuff[]': $w('$ a ;') }, + + value_undefined: { a:"b", c:undefined }, + value_null: { a:"b", c:null }, + value_zero: { a:"b", c:0 } +}; + +new Test.Unit.Runner({ + testSet: function() { + var h = $H({a: 'A'}) + + this.assertEqual('B', h.set('b', 'B')); + this.assertHashEqual({a: 'A', b: 'B'}, h); + + this.assertUndefined(h.set('c')); + this.assertHashEqual({a: 'A', b: 'B', c: undefined}, h); + }, + + testGet: function() { + var h = $H({a: 'A'}); + this.assertEqual('A', h.get('a')); + this.assertUndefined(h.a); + this.assertUndefined($H({}).get('a')); + }, + + testUnset: function() { + var hash = $H(Fixtures.many); + this.assertEqual('B', hash.unset('b')); + this.assertHashEqual({a:'A', c: 'C', d:'D#'}, hash); + this.assertUndefined(hash.unset('z')); + this.assertHashEqual({a:'A', c: 'C', d:'D#'}, hash); + // not equivalent to Hash#remove + this.assertEqual('A', hash.unset('a', 'c')); + this.assertHashEqual({c: 'C', d:'D#'}, hash); + }, + + testToObject: function() { + var hash = $H(Fixtures.many), object = hash.toObject(); + this.assertInstanceOf(Object, object); + this.assertHashEqual(Fixtures.many, object); + this.assertNotIdentical(Fixtures.many, object); + hash.set('foo', 'bar'); + this.assertHashNotEqual(object, hash.toObject()); + }, + + testConstruct: function() { + var object = Object.clone(Fixtures.one); + var h = new Hash(object), h2 = $H(object); + this.assertInstanceOf(Hash, h); + this.assertInstanceOf(Hash, h2); + + this.assertHashEqual({}, new Hash()); + this.assertHashEqual(object, h); + this.assertHashEqual(object, h2); + + h.set('foo', 'bar'); + this.assertHashNotEqual(object, h); + + var clone = $H(h); + this.assertInstanceOf(Hash, clone); + this.assertHashEqual(h, clone); + h.set('foo', 'foo'); + this.assertHashNotEqual(h, clone); + this.assertIdentical($H, Hash.from); + }, + + testKeys: function() { + this.assertEnumEqual([], $H({}).keys()); + this.assertEnumEqual(['a'], $H(Fixtures.one).keys()); + this.assertEnumEqual($w('a b c d'), $H(Fixtures.many).keys().sort()); + this.assertEnumEqual($w('plus quad'), $H(Fixtures.functions).keys().sort()); + }, + + testValues: function() { + this.assertEnumEqual([], $H({}).values()); + this.assertEnumEqual(['A#'], $H(Fixtures.one).values()); + this.assertEnumEqual($w('A B C D#'), $H(Fixtures.many).values().sort()); + this.assertEnumEqual($w('function function'), + $H(Fixtures.functions).values().map(function(i){ return typeof i })); + this.assertEqual(9, $H(Fixtures.functions).get('quad')(3)); + this.assertEqual(6, $H(Fixtures.functions).get('plus')(3)); + }, + + testIndex: function() { + this.assertUndefined($H().index('foo')); + + this.assert('a', $H(Fixtures.one).index('A#')); + this.assert('a', $H(Fixtures.many).index('A')); + this.assertUndefined($H(Fixtures.many).index('Z')) + + var hash = $H({a:1,b:'2',c:1}); + this.assert(['a','c'].include(hash.index(1))); + this.assertUndefined(hash.index('1')); + }, + + testMerge: function() { + var h = $H(Fixtures.many); + this.assertNotIdentical(h, h.merge()); + this.assertNotIdentical(h, h.merge({})); + this.assertInstanceOf(Hash, h.merge()); + this.assertInstanceOf(Hash, h.merge({})); + this.assertHashEqual(h, h.merge()); + this.assertHashEqual(h, h.merge({})); + this.assertHashEqual(h, h.merge($H())); + this.assertHashEqual({a:'A', b:'B', c:'C', d:'D#', aaa:'AAA' }, h.merge({aaa: 'AAA'})); + this.assertHashEqual({a:'A#', b:'B', c:'C', d:'D#' }, h.merge(Fixtures.one)); + }, + + testUpdate: function() { + var h = $H(Fixtures.many); + this.assertIdentical(h, h.update()); + this.assertIdentical(h, h.update({})); + this.assertHashEqual(h, h.update()); + this.assertHashEqual(h, h.update({})); + this.assertHashEqual(h, h.update($H())); + this.assertHashEqual({a:'A', b:'B', c:'C', d:'D#', aaa:'AAA' }, h.update({aaa: 'AAA'})); + this.assertHashEqual({a:'A#', b:'B', c:'C', d:'D#', aaa:'AAA' }, h.update(Fixtures.one)); + }, + + testToQueryString: function() { + this.assertEqual('', $H({}).toQueryString()); + this.assertEqual('a%23=A', $H({'a#': 'A'}).toQueryString()); + this.assertEqual('a=A%23', $H(Fixtures.one).toQueryString()); + this.assertEqual('a=A&b=B&c=C&d=D%23', $H(Fixtures.many).toQueryString()); + this.assertEqual("a=b&c", $H(Fixtures.value_undefined).toQueryString()); + this.assertEqual("a=b&c", $H("a=b&c".toQueryParams()).toQueryString()); + this.assertEqual("a=b&c=", $H(Fixtures.value_null).toQueryString()); + this.assertEqual("a=b&c=0", $H(Fixtures.value_zero).toQueryString()); + this.assertEqual("color=r&color=g&color=b", $H(Fixtures.multiple).toQueryString()); + this.assertEqual("color=r&color=&color=g&color&color=0", $H(Fixtures.multiple_nil).toQueryString()); + this.assertEqual("color=&color", $H(Fixtures.multiple_all_nil).toQueryString()); + this.assertEqual("", $H(Fixtures.multiple_empty).toQueryString()); + this.assertEqual("", $H({foo: {}, bar: {}}).toQueryString()); + this.assertEqual("stuff%5B%5D=%24&stuff%5B%5D=a&stuff%5B%5D=%3B", $H(Fixtures.multiple_special).toQueryString()); + this.assertHashEqual(Fixtures.multiple_special, $H(Fixtures.multiple_special).toQueryString().toQueryParams()); + this.assertIdentical(Object.toQueryString, Hash.toQueryString); + }, + + testInspect: function() { + this.assertEqual('#', $H({}).inspect()); + this.assertEqual("#", $H(Fixtures.one).inspect()); + this.assertEqual("#", $H(Fixtures.many).inspect()); + }, + + testClone: function() { + var h = $H(Fixtures.many); + this.assertHashEqual(h, h.clone()); + this.assertInstanceOf(Hash, h.clone()); + this.assertNotIdentical(h, h.clone()); + }, + + testToJSON: function() { + this.assertEqual('{\"b\": [false, true], \"c\": {\"a\": \"hello!\"}}', + $H({'b': [undefined, false, true, undefined], c: {a: 'hello!'}}).toJSON()); + }, + + testAbilityToContainAnyKey: function() { + var h = $H({ _each: 'E', map: 'M', keys: 'K', pluck: 'P', unset: 'U' }); + this.assertEnumEqual($w('_each keys map pluck unset'), h.keys().sort()); + this.assertEqual('U', h.unset('unset')); + this.assertHashEqual({ _each: 'E', map: 'M', keys: 'K', pluck: 'P' }, h); + }, + + testHashToTemplateReplacements: function() { + var template = new Template("#{a} #{b}"), hash = $H({ a: "hello", b: "world" }); + this.assertEqual("hello world", template.evaluate(hash.toObject())); + this.assertEqual("hello world", template.evaluate(hash)); + this.assertEqual("hello", "#{a}".interpolate(hash)); + }, + + testPreventIterationOverShadowedProperties: function() { + // redundant now that object is systematically cloned. + var FooMaker = function(value) { + this.key = value; + }; + FooMaker.prototype.key = 'foo'; + var foo = new FooMaker('bar'); + this.assertEqual("key=bar", new Hash(foo).toQueryString()); + this.assertEqual("key=bar", new Hash(new Hash(foo)).toQueryString()); + } + +}); \ No newline at end of file diff --git a/test/unit/number.html b/test/unit/number.html deleted file mode 100644 index a323f2f..0000000 --- a/test/unit/number.html +++ /dev/null @@ -1,63 +0,0 @@ - - - - Prototype Unit test file - - - - - - -

Prototype Unit test file

-

- Test of utility functions in number.js -

- - -
- - - - - diff --git a/test/unit/number_test.js b/test/unit/number_test.js new file mode 100644 index 0000000..662d828 --- /dev/null +++ b/test/unit/number_test.js @@ -0,0 +1,34 @@ +new Test.Unit.Runner({ + + testNumberMathMethods: function() { + this.assertEqual(1, (0.9).round()); + this.assertEqual(-2, (-1.9).floor()); + this.assertEqual(-1, (-1.9).ceil()); + + $w('abs floor round ceil').each(function(method) { + this.assertEqual(Math[method](Math.PI), Math.PI[method]()); + }, this); + }, + + testNumberToColorPart: function() { + this.assertEqual('00', (0).toColorPart()); + this.assertEqual('0a', (10).toColorPart()); + this.assertEqual('ff', (255).toColorPart()); + }, + + testNumberToPaddedString: function() { + this.assertEqual('00', (0).toPaddedString(2, 16)); + this.assertEqual('0a', (10).toPaddedString(2, 16)); + this.assertEqual('ff', (255).toPaddedString(2, 16)); + this.assertEqual('000', (0).toPaddedString(3)); + this.assertEqual('010', (10).toPaddedString(3)); + this.assertEqual('100', (100).toPaddedString(3)); + this.assertEqual('1000', (1000).toPaddedString(3)); + }, + + testNumberToJSON: function() { + this.assertEqual('null', Number.NaN.toJSON()); + this.assertEqual('0', (0).toJSON()); + this.assertEqual('-293', (-293).toJSON()); + } +}); \ No newline at end of file diff --git a/test/unit/position.html b/test/unit/position.html deleted file mode 100644 index 4d4fe57..0000000 --- a/test/unit/position.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - Prototype Unit test file - - - - - - -
- -

Prototype Unit test file

-

- Test of functions in position.js -

- - -
- -
-
-
-
testtest
-
-
-
- - - - - diff --git a/test/unit/position_test.js b/test/unit/position_test.js new file mode 100644 index 0000000..5cea791 --- /dev/null +++ b/test/unit/position_test.js @@ -0,0 +1,44 @@ +var testVar = 'to be updated'; + +new Test.Unit.Runner({ + + setup: function() { + scrollTo(0,0); + Position.prepare(); + Position.includeScrollOffsets = false; + }, + + teardown: function() { + scrollTo(0,0); + Position.prepare(); + Position.includeScrollOffsets = false; + }, + + testPrepare: function() { + Position.prepare(); + this.assertEqual(0, Position.deltaX); + this.assertEqual(0, Position.deltaY); + scrollTo(20,30); + Position.prepare(); + this.assertEqual(20, Position.deltaX); + this.assertEqual(30, Position.deltaY); + }, + + testWithin: function() { + [true, false].each(function(withScrollOffsets) { + Position.includeScrollOffsets = withScrollOffsets; + this.assert(!Position.within($('body_absolute'), 9, 9), 'outside left/top'); + this.assert(Position.within($('body_absolute'), 10, 10), 'left/top corner'); + this.assert(Position.within($('body_absolute'), 10, 19), 'left/bottom corner'); + this.assert(!Position.within($('body_absolute'), 10, 20), 'outside bottom'); + }, this); + + scrollTo(20,30); + Position.prepare(); + Position.includeScrollOffsets = true; + this.assert(!Position.within($('body_absolute'), 9, 9), 'outside left/top'); + this.assert(Position.within($('body_absolute'), 10, 10), 'left/top corner'); + this.assert(Position.within($('body_absolute'), 10, 19), 'left/bottom corner'); + this.assert(!Position.within($('body_absolute'), 10, 20), 'outside bottom'); + } +}); \ No newline at end of file diff --git a/test/unit/range.html b/test/unit/range.html deleted file mode 100644 index 0f71cdc..0000000 --- a/test/unit/range.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - Prototype Unit test file - - - - - - -

Prototype Unit test file

-

- Test of utility functions in range.js -

- - -
- - - - - \ No newline at end of file diff --git a/test/unit/range_test.js b/test/unit/range_test.js new file mode 100644 index 0000000..bcf5acb --- /dev/null +++ b/test/unit/range_test.js @@ -0,0 +1,58 @@ +new Test.Unit.Runner({ + + testInclude: function() { + this.assert(!$R(0, 0, true).include(0)); + this.assert($R(0, 0, false).include(0)); + + this.assert($R(0, 5, true).include(0)); + this.assert($R(0, 5, true).include(4)); + this.assert(!$R(0, 5, true).include(5)); + + this.assert($R(0, 5, false).include(0)); + this.assert($R(0, 5, false).include(5)); + this.assert(!$R(0, 5, false).include(6)); + }, + + testEach: function() { + var results = []; + $R(0, 0, true).each(function(value) { + results.push(value); + }); + + this.assertEnumEqual([], results); + + results = []; + $R(0, 3, false).each(function(value) { + results.push(value); + }); + + this.assertEnumEqual([0, 1, 2, 3], results); + }, + + testAny: function() { + this.assert(!$R(1, 1, true).any()); + this.assert($R(0, 3, false).any(function(value) { + return value == 3; + })); + }, + + testAll: function() { + this.assert($R(1, 1, true).all()); + this.assert($R(0, 3, false).all(function(value) { + return value <= 3; + })); + }, + + testToArray: function() { + this.assertEnumEqual([], $R(0, 0, true).toArray()); + this.assertEnumEqual([0], $R(0, 0, false).toArray()); + this.assertEnumEqual([0], $R(0, 1, true).toArray()); + this.assertEnumEqual([0, 1], $R(0, 1, false).toArray()); + this.assertEnumEqual([-3, -2, -1, 0, 1, 2], $R(-3, 3, true).toArray()); + this.assertEnumEqual([-3, -2, -1, 0, 1, 2, 3], $R(-3, 3, false).toArray()); + }, + + testDefaultsToNotExclusive: function() { + this.assertEnumEqual($R(-3,3), $R(-3,3,false)); + } +}); \ No newline at end of file diff --git a/test/unit/selector.html b/test/unit/selector.html deleted file mode 100644 index 3a8c9ac..0000000 --- a/test/unit/selector.html +++ /dev/null @@ -1,477 +0,0 @@ - - - - Prototype Unit test file - - - - - - -

Prototype Unit test file

-

- Test of utility functions in selector.js -

- - - - -
- - - - - diff --git a/test/unit/selector_test.js b/test/unit/selector_test.js new file mode 100644 index 0000000..519dd98 --- /dev/null +++ b/test/unit/selector_test.js @@ -0,0 +1,377 @@ +var $RunBenchmarks = false; + +new Test.Unit.Runner({ + + testSelectorWithTagName: function() { + this.assertEnumEqual($A(document.getElementsByTagName('li')), $$('li')); + this.assertEnumEqual([$('strong')], $$('strong')); + this.assertEnumEqual([], $$('nonexistent')); + + var allNodes = $A(document.getElementsByTagName('*')).select( function(node) { + return node.tagName !== '!'; + }); + this.assertEnumEqual(allNodes, $$('*')); + }, + + testSelectorWithId: function() { + this.assertEnumEqual([$('fixtures')], $$('#fixtures')); + this.assertEnumEqual([], $$('#nonexistent')); + this.assertEnumEqual([$('troubleForm')], $$('#troubleForm')); + }, + + testSelectorWithClassName: function() { + this.assertEnumEqual($('p', 'link_1', 'item_1'), $$('.first')); + this.assertEnumEqual([], $$('.second')); + }, + + testSelectorWithTagNameAndId: function() { + this.assertEnumEqual([$('strong')], $$('strong#strong')); + this.assertEnumEqual([], $$('p#strong')); + }, + + testSelectorWithTagNameAndClassName: function() { + this.assertEnumEqual($('link_1', 'link_2'), $$('a.internal')); + this.assertEnumEqual([$('link_2')], $$('a.internal.highlight')); + this.assertEnumEqual([$('link_2')], $$('a.highlight.internal')); + this.assertEnumEqual([], $$('a.highlight.internal.nonexistent')); + }, + + testSelectorWithIdAndClassName: function() { + this.assertEnumEqual([$('link_2')], $$('#link_2.internal')); + this.assertEnumEqual([$('link_2')], $$('.internal#link_2')); + this.assertEnumEqual([$('link_2')], $$('#link_2.internal.highlight')); + this.assertEnumEqual([], $$('#link_2.internal.nonexistent')); + }, + + testSelectorWithTagNameAndIdAndClassName: function() { + this.assertEnumEqual([$('link_2')], $$('a#link_2.internal')); + this.assertEnumEqual([$('link_2')], $$('a.internal#link_2')); + this.assertEnumEqual([$('item_1')], $$('li#item_1.first')); + this.assertEnumEqual([], $$('li#item_1.nonexistent')); + this.assertEnumEqual([], $$('li#item_1.first.nonexistent')); + }, + + test$$MatchesAncestryWithTokensSeparatedByWhitespace: function() { + this.assertEnumEqual($('em2', 'em', 'span'), $$('#fixtures a *')); + this.assertEnumEqual([$('p')], $$('div#fixtures p')); + }, + + test$$CombinesResultsWhenMultipleExpressionsArePassed: function() { + this.assertEnumEqual($('link_1', 'link_2', 'item_1', 'item_2', 'item_3'), $$('#p a', ' ul#list li ')); + }, + + testSelectorWithTagNameAndAttributeExistence: function() { + this.assertEnumEqual($$('#fixtures h1'), $$('h1[class]'), 'h1[class]'); + this.assertEnumEqual($$('#fixtures h1'), $$('h1[CLASS]'), 'h1[CLASS]'); + this.assertEnumEqual([$('item_3')], $$('li#item_3[class]'), 'li#item_3[class]'); + }, + + testSelectorWithTagNameAndSpecificAttributeValue: function() { + this.assertEnumEqual($('link_1', 'link_2', 'link_3'), $$('a[href="#"]')); + this.assertEnumEqual($('link_1', 'link_2', 'link_3'), $$('a[href=#]')); + }, + + testSelectorWithTagNameAndWhitespaceTokenizedAttributeValue: function() { + this.assertEnumEqual($('link_1', 'link_2'), $$('a[class~="internal"]'), "a[class~=\"internal\"]"); + this.assertEnumEqual($('link_1', 'link_2'), $$('a[class~=internal]'), "a[class~=internal]"); + }, + + testSelectorWithAttributeAndNoTagName: function() { + this.assertEnumEqual($(document.body).select('a[href]'), $(document.body).select('[href]')); + this.assertEnumEqual($$('a[class~="internal"]'), $$('[class~=internal]')); + this.assertEnumEqual($$('*[id]'), $$('[id]')); + this.assertEnumEqual($('checked_radio', 'unchecked_radio'), $$('[type=radio]')); + this.assertEnumEqual($$('*[type=checkbox]'), $$('[type=checkbox]')); + this.assertEnumEqual($('with_title', 'commaParent'), $$('[title]')); + this.assertEnumEqual($$('#troubleForm *[type=radio]'), $$('#troubleForm [type=radio]')); + this.assertEnumEqual($$('#troubleForm *[type]'), $$('#troubleForm [type]')); + }, + + testSelectorWithUniversalAndHyphenTokenizedAttributeValue: function() { + this.assertEnumEqual([$('item_3')], $$('*[xml:lang|="es"]')); + this.assertEnumEqual([$('item_3')], $$('*[xml:lang|="ES"]')); + }, + + testSelectorWithTagNameAndNegatedAttributeValue: function() { + this.assertEnumEqual([], $$('a[href!="#"]')); + }, + + testSelectorWithBracketAttributeValue: function() { + this.assertEnumEqual($('chk_1', 'chk_2'), $$('#troubleForm2 input[name="brackets[5][]"]')); + this.assertEnumEqual([$('chk_1')], $$('#troubleForm2 input[name="brackets[5][]"]:checked')); + this.assertEnumEqual([$('chk_2')], $$('#troubleForm2 input[name="brackets[5][]"][value=2]')); + this.assertEnumEqual([], $$('#troubleForm2 input[name=brackets[5][]]')); + }, + + test$$WithNestedAttributeSelectors: function() { + this.assertEnumEqual([$('strong')], $$('div[style] p[id] strong'), 'div[style] p[id] strong'); + }, + + testSelectorWithMultipleConditions: function() { + this.assertEnumEqual([$('link_3')], $$('a[class~=external][href="#"]'), + 'a[class~=external][href="#"]'); + this.assertEnumEqual([], $$('a[class~=external][href!="#"]'), + 'a[class~=external][href!="#"]'); + }, + + testSelectorMatchElements: function() { + this.assertElementsMatch(Selector.matchElements($('list').descendants(), 'li'), '#item_1', '#item_2', '#item_3'); + this.assertElementsMatch(Selector.matchElements($('fixtures').descendants(), 'a.internal'), '#link_1', '#link_2'); + this.assertEnumEqual([], Selector.matchElements($('fixtures').descendants(), 'p.last')); + this.assertElementsMatch(Selector.matchElements($('fixtures').descendants(), '.inexistant, a.internal'), '#link_1', '#link_2'); + }, + + testSelectorFindElement: function() { + this.assertElementMatches(Selector.findElement($('list').descendants(), 'li'), 'li#item_1.first'); + this.assertElementMatches(Selector.findElement($('list').descendants(), 'li', 1), 'li#item_2'); + this.assertElementMatches(Selector.findElement($('list').descendants(), 'li#item_3'), 'li'); + this.assertEqual(undefined, Selector.findElement($('list').descendants(), 'em')); + }, + + testElementMatch: function() { + var span = $('dupL1'); + + // tests that should pass + this.assert(span.match('span')); + this.assert(span.match('span#dupL1')); + this.assert(span.match('div > span'), 'child combinator'); + this.assert(span.match('#dupContainer span'), 'descendant combinator'); + this.assert(span.match('#dupL1'), 'ID only'); + this.assert(span.match('span.span_foo'), 'class name 1'); + this.assert(span.match('span.span_bar'), 'class name 2'); + this.assert(span.match('span:first-child'), 'first-child pseudoclass'); + + this.assert(!span.match('span.span_wtf'), 'bogus class name'); + this.assert(!span.match('#dupL2'), 'different ID'); + this.assert(!span.match('div'), 'different tag name'); + this.assert(!span.match('span span'), 'different ancestry'); + this.assert(!span.match('span > span'), 'different parent'); + this.assert(!span.match('span:nth-child(5)'), 'different pseudoclass'); + + this.assert(!$('link_2').match('a[rel^=external]')); + this.assert($('link_1').match('a[rel^=external]')); + this.assert($('link_1').match('a[rel^="external"]')); + this.assert($('link_1').match("a[rel^='external']")); + + this.assert(span.match({ match: function(element) { return true }}), 'custom selector'); + this.assert(!span.match({ match: function(element) { return false }}), 'custom selector'); + }, + + testSelectorWithSpaceInAttributeValue: function() { + this.assertEnumEqual([$('with_title')], $$('cite[title="hello world!"]')); + }, + + // AND NOW COME THOSE NEW TESTS AFTER ANDREW'S REWRITE! + + testSelectorWithNamespacedAttributes: function() { + if (Prototype.BrowserFeatures.XPath) { + this.assertUndefined(new Selector('html[xml:lang]').xpath); + this.assertUndefined(new Selector('body p[xml:lang]').xpath); + } else + this.info("Could not test XPath bypass: no XPath to begin with!"); + + this.assertElementsMatch($$('[xml:lang]'), 'html', '#item_3'); + this.assertElementsMatch($$('*[xml:lang]'), 'html', '#item_3'); + }, + + testSelectorWithChild: function() { + this.assertEnumEqual($('link_1', 'link_2'), $$('p.first > a')); + this.assertEnumEqual($('father', 'uncle'), $$('div#grandfather > div')); + this.assertEnumEqual($('level2_1', 'level2_2'), $$('#level1>span')); + this.assertEnumEqual($('level2_1', 'level2_2'), $$('#level1 > span')); + this.assertEnumEqual($('level3_1', 'level3_2'), $$('#level2_1 > *')); + this.assertEnumEqual([], $$('div > #nonexistent')); + $RunBenchmarks && this.wait(500, function() { + this.benchmark(function() { $$('#level1 > span') }, 1000); + }); + }, + + testSelectorWithAdjacence: function() { + this.assertEnumEqual([$('uncle')], $$('div.brothers + div.brothers')); + this.assertEnumEqual([$('uncle')], $$('div.brothers + div')); + this.assertEqual($('level2_2'), $$('#level2_1+span').reduce()); + this.assertEqual($('level2_2'), $$('#level2_1 + span').reduce()); + this.assertEqual($('level2_2'), $$('#level2_1 + *').reduce()); + this.assertEnumEqual([], $$('#level2_2 + span')); + this.assertEqual($('level3_2'), $$('#level3_1 + span').reduce()); + this.assertEqual($('level3_2'), $$('#level3_1 + *').reduce()); + this.assertEnumEqual([], $$('#level3_2 + *')); + this.assertEnumEqual([], $$('#level3_1 + em')); + $RunBenchmarks && this.wait(500, function() { + this.benchmark(function() { $$('#level3_1 + span') }, 1000); + }); + }, + + testSelectorWithLaterSibling: function() { + this.assertEnumEqual([$('list')], $$('h1 ~ ul')); + this.assertEqual($('level2_2'), $$('#level2_1 ~ span').reduce()); + this.assertEnumEqual($('level2_2', 'level2_3'), $$('#level2_1 ~ *').reduce()); + this.assertEnumEqual([], $$('#level2_2 ~ span')); + this.assertEnumEqual([], $$('#level3_2 ~ *')); + this.assertEnumEqual([], $$('#level3_1 ~ em')); + this.assertEnumEqual([$('level3_2')], $$('#level3_1 ~ #level3_2')); + this.assertEnumEqual([$('level3_2')], $$('span ~ #level3_2')); + this.assertEnumEqual([], $$('div ~ #level3_2')); + this.assertEnumEqual([], $$('div ~ #level2_3')); + $RunBenchmarks && this.wait(500, function() { + this.benchmark(function() { $$('#level2_1 ~ span') }, 1000); + }); + }, + + testSelectorWithNewAttributeOperators: function() { + this.assertEnumEqual($('father', 'uncle'), $$('div[class^=bro]'), 'matching beginning of string'); + this.assertEnumEqual($('father', 'uncle'), $$('div[class$=men]'), 'matching end of string'); + this.assertEnumEqual($('father', 'uncle'), $$('div[class*="ers m"]'), 'matching substring') + this.assertEnumEqual($('level2_1', 'level2_2', 'level2_3'), $$('#level1 *[id^="level2_"]')); + this.assertEnumEqual($('level2_1', 'level2_2', 'level2_3'), $$('#level1 *[id^=level2_]')); + this.assertEnumEqual($('level2_1', 'level3_1'), $$('#level1 *[id$="_1"]')); + this.assertEnumEqual($('level2_1', 'level3_1'), $$('#level1 *[id$=_1]')); + this.assertEnumEqual($('level2_1', 'level3_2', 'level2_2', 'level2_3'), $$('#level1 *[id*="2"]')); + this.assertEnumEqual($('level2_1', 'level3_2', 'level2_2', 'level2_3'), $$('#level1 *[id*=2]')); + $RunBenchmarks && this.wait(500, function() { + this.benchmark(function() { $$('#level1 *[id^=level2_]') }, 1000, '[^=]'); + this.benchmark(function() { $$('#level1 *[id$=_1]') }, 1000, '[$=]'); + this.benchmark(function() { $$('#level1 *[id*=_2]') }, 1000, '[*=]'); + }); + }, + + testSelectorWithDuplicates: function() { + this.assertEnumEqual($$('div div'), $$('div div').uniq()); + this.assertEnumEqual($('dupL2', 'dupL3', 'dupL4', 'dupL5'), $$('#dupContainer span span')); + $RunBenchmarks && this.wait(500, function() { + this.benchmark(function() { $$('#dupContainer span span') }, 1000); + }); + }, + + testSelectorWithFirstLastOnlyNthNthLastChild: function() { + this.assertEnumEqual([$('level2_1')], $$('#level1>*:first-child')); + this.assertEnumEqual($('level2_1', 'level3_1', 'level_only_child'), $$('#level1 *:first-child')); + this.assertEnumEqual([$('level2_3')], $$('#level1>*:last-child')); + this.assertEnumEqual($('level3_2', 'level_only_child', 'level2_3'), $$('#level1 *:last-child')); + this.assertEnumEqual([$('level2_3')], $$('#level1>div:last-child')); + this.assertEnumEqual([$('level2_3')], $$('#level1 div:last-child')); + this.assertEnumEqual([], $$('#level1>div:first-child')); + this.assertEnumEqual([], $$('#level1>span:last-child')); + this.assertEnumEqual($('level2_1', 'level3_1'), $$('#level1 span:first-child')); + this.assertEnumEqual([], $$('#level1:first-child')); + this.assertEnumEqual([], $$('#level1>*:only-child')); + this.assertEnumEqual([$('level_only_child')], $$('#level1 *:only-child')); + this.assertEnumEqual([], $$('#level1:only-child')); + this.assertEnumEqual([$('link_2')], $$('#p *:nth-last-child(2)'), 'nth-last-child'); + this.assertEnumEqual([$('link_2')], $$('#p *:nth-child(3)'), 'nth-child'); + this.assertEnumEqual([$('link_2')], $$('#p a:nth-child(3)'), 'nth-child'); + this.assertEnumEqual($('item_2', 'item_3'), $$('#list > li:nth-child(n+2)')); + this.assertEnumEqual($('item_1', 'item_2'), $$('#list > li:nth-child(-n+2)')); + $RunBenchmarks && this.wait(500, function() { + this.benchmark(function() { $$('#level1 *:first-child') }, 1000, ':first-child'); + this.benchmark(function() { $$('#level1 *:last-child') }, 1000, ':last-child'); + this.benchmark(function() { $$('#level1 *:only-child') }, 1000, ':only-child'); + }); + }, + + testSelectorWithFirstLastNthNthLastOfType: function() { + this.assertEnumEqual([$('link_2')], $$('#p a:nth-of-type(2)'), 'nth-of-type'); + this.assertEnumEqual([$('link_1')], $$('#p a:nth-of-type(1)'), 'nth-of-type'); + this.assertEnumEqual([$('link_2')], $$('#p a:nth-last-of-type(1)'), 'nth-last-of-type'); + this.assertEnumEqual([$('link_1')], $$('#p a:first-of-type'), 'first-of-type'); + this.assertEnumEqual([$('link_2')], $$('#p a:last-of-type'), 'last-of-type'); + }, + + testSelectorWithNot: function() { + this.assertEnumEqual([$('link_2')], $$('#p a:not(a:first-of-type)'), 'first-of-type'); + this.assertEnumEqual([$('link_1')], $$('#p a:not(a:last-of-type)'), 'last-of-type'); + this.assertEnumEqual([$('link_2')], $$('#p a:not(a:nth-of-type(1))'), 'nth-of-type'); + this.assertEnumEqual([$('link_1')], $$('#p a:not(a:nth-last-of-type(1))'), 'nth-last-of-type'); + this.assertEnumEqual([$('link_2')], $$('#p a:not([rel~=nofollow])'), 'attribute 1'); + this.assertEnumEqual([$('link_2')], $$('#p a:not(a[rel^=external])'), 'attribute 2'); + this.assertEnumEqual([$('link_2')], $$('#p a:not(a[rel$=nofollow])'), 'attribute 3'); + this.assertEnumEqual([$('em')], $$('#p a:not(a[rel$="nofollow"]) > em'), 'attribute 4') + this.assertEnumEqual([$('item_2')], $$('#list li:not(#item_1):not(#item_3)'), 'adjacent :not clauses'); + this.assertEnumEqual([$('son')], $$('#grandfather > div:not(#uncle) #son')); + this.assertEnumEqual([$('em')], $$('#p a:not(a[rel$="nofollow"]) em'), 'attribute 4 + all descendants'); + this.assertEnumEqual([$('em')], $$('#p a:not(a[rel$="nofollow"])>em'), 'attribute 4 (without whitespace)'); + }, + + testSelectorWithEnabledDisabledChecked: function() { + this.assertEnumEqual([$('disabled_text_field')], $$('#troubleForm > *:disabled')); + this.assertEnumEqual($('troubleForm').getInputs().without($('disabled_text_field'), $('hidden')), $$('#troubleForm > *:enabled')); + this.assertEnumEqual($('checked_box', 'checked_radio'), $$('#troubleForm *:checked')); + }, + + testSelectorWithEmpty: function() { + $('level3_1').innerHTML = ""; + this.assertEnumEqual($('level3_1', 'level3_2', 'level2_3'), + $$('#level1 *:empty'), '#level1 *:empty'); + this.assertEnumEqual([], $$('#level_only_child:empty'), 'newlines count as content!'); + }, + + testIdenticalResultsFromEquivalentSelectors: function() { + this.assertEnumEqual($$('div.brothers'), $$('div[class~=brothers]')); + this.assertEnumEqual($$('div.brothers'), $$('div[class~=brothers].brothers')); + this.assertEnumEqual($$('div:not(.brothers)'), $$('div:not([class~=brothers])')); + this.assertEnumEqual($$('li ~ li'), $$('li:not(:first-child)')); + this.assertEnumEqual($$('ul > li'), $$('ul > li:nth-child(n)')); + this.assertEnumEqual($$('ul > li:nth-child(even)'), $$('ul > li:nth-child(2n)')); + this.assertEnumEqual($$('ul > li:nth-child(odd)'), $$('ul > li:nth-child(2n+1)')); + this.assertEnumEqual($$('ul > li:first-child'), $$('ul > li:nth-child(1)')); + this.assertEnumEqual($$('ul > li:last-child'), $$('ul > li:nth-last-child(1)')); + this.assertEnumEqual($$('ul > li:nth-child(n-999)'), $$('ul > li')); + this.assertEnumEqual($$('ul>li'), $$('ul > li')); + this.assertEnumEqual($$('#p a:not(a[rel$="nofollow"])>em'), $$('#p a:not(a[rel$="nofollow"]) > em')) + }, + + testSelectorsThatShouldReturnNothing: function() { + this.assertEnumEqual([], $$('span:empty > *')); + this.assertEnumEqual([], $$('div.brothers:not(.brothers)')); + this.assertEnumEqual([], $$('#level2_2 :only-child:not(:last-child)')); + this.assertEnumEqual([], $$('#level2_2 :only-child:not(:first-child)')); + }, + + testCommasFor$$: function() { + this.assertEnumEqual($('list', 'p', 'link_1', 'item_1', 'item_3', 'troubleForm'), $$('#list, .first,*[xml:lang="es-us"] , #troubleForm')); + this.assertEnumEqual($('list', 'p', 'link_1', 'item_1', 'item_3', 'troubleForm'), $$('#list, .first,', '*[xml:lang="es-us"] , #troubleForm')); + this.assertEnumEqual($('commaParent', 'commaChild'), $$('form[title*="commas,"], input[value="#commaOne,#commaTwo"]')); + this.assertEnumEqual($('commaParent', 'commaChild'), $$('form[title*="commas,"]', 'input[value="#commaOne,#commaTwo"]')); + }, + + testSelectorExtendsAllNodes: function(){ + var element = document.createElement('div'); + (3).times(function(){ + element.appendChild(document.createElement('div')); + }); + element.setAttribute('id','scratch_element'); + $$('body')[0].appendChild(element); + + var results = $$('#scratch_element div'); + this.assert(typeof results[0].show == 'function'); + this.assert(typeof results[1].show == 'function'); + this.assert(typeof results[2].show == 'function'); + }, + + testCountedIsNotAnAttribute: function() { + var el = $('list'); + Selector.handlers.mark([el]); + this.assert(!el.innerHTML.include("_counted")); + Selector.handlers.unmark([el]); + this.assert(!el.innerHTML.include("_counted")); + }, + + testCopiedNodesGetIncluded: function() { + this.assertElementsMatch( + Selector.matchElements($('counted_container').descendants(), 'div'), + 'div.is_counted' + ); + $('counted_container').innerHTML += $('counted_container').innerHTML; + this.assertElementsMatch( + Selector.matchElements($('counted_container').descendants(), 'div'), 'div.is_counted', + 'div.is_counted' + ); + }, + + testElementDown: function() { + var a = $('dupL4'); + var b = $('dupContainer').down('#dupL4'); + + this.assertEqual(a, b); + } +}); \ No newline at end of file diff --git a/test/unit/string.html b/test/unit/string.html deleted file mode 100644 index ac8ceab..0000000 --- a/test/unit/string.html +++ /dev/null @@ -1,563 +0,0 @@ - - - - Prototype Unit test file - - - - - - -

Prototype Unit test file

-

- Test of utility functions in string.js -

- - -
- - - - - diff --git a/test/unit/string_test.js b/test/unit/string_test.js new file mode 100644 index 0000000..cf1b490 --- /dev/null +++ b/test/unit/string_test.js @@ -0,0 +1,537 @@ +var attackTarget; +var evalScriptsCounter = 0, + largeTextEscaped = '<span>test</span>', + largeTextUnescaped = 'test'; +(2048).times(function(){ + largeTextEscaped += ' ABC'; + largeTextUnescaped += ' ABC'; +}); + +new Test.Unit.Runner({ + testInterpret: function(){ + this.assertIdentical('true', String.interpret(true)); + this.assertIdentical('123', String.interpret(123)); + this.assertIdentical('foo bar', String.interpret('foo bar')); + this.assertIdentical( + 'object string', + String.interpret({ toString: function(){ return 'object string' } })); + + this.assertIdentical('0', String.interpret(0)); + this.assertIdentical('false', String.interpret(false)); + this.assertIdentical('', String.interpret(undefined)); + this.assertIdentical('', String.interpret(null)); + this.assertIdentical('', String.interpret('')); + }, + + testGsubWithReplacementFunction: function() { + var source = 'foo boo boz'; + + this.assertEqual('Foo Boo BoZ', + source.gsub(/[^o]+/, function(match) { + return match[0].toUpperCase() + })); + this.assertEqual('f2 b2 b1z', + source.gsub(/o+/, function(match) { + return match[0].length; + })); + this.assertEqual('f0 b0 b1z', + source.gsub(/o+/, function(match) { + return match[0].length % 2; + })); + + }, + + testGsubWithReplacementString: function() { + var source = 'foo boo boz'; + + this.assertEqual('foobooboz', + source.gsub(/\s+/, '')); + this.assertEqual(' z', + source.gsub(/(.)(o+)/, '')); + + this.assertEqual('ウィメンズ2007
クルーズコレクション', + 'ウィメンズ2007\nクルーズコレクション'.gsub(/\n/,'
')); + this.assertEqual('ウィメンズ2007
クルーズコレクション', + 'ウィメンズ2007\nクルーズコレクション'.gsub('\n','
')); + }, + + testGsubWithReplacementTemplateString: function() { + var source = 'foo boo boz'; + + this.assertEqual('-oo-#{1}- -oo-#{1}- -o-#{1}-z', + source.gsub(/(.)(o+)/, '-#{2}-\\#{1}-')); + this.assertEqual('-foo-f- -boo-b- -bo-b-z', + source.gsub(/(.)(o+)/, '-#{0}-#{1}-')); + this.assertEqual('-oo-f- -oo-b- -o-b-z', + source.gsub(/(.)(o+)/, '-#{2}-#{1}-')); + this.assertEqual(' z', + source.gsub(/(.)(o+)/, '#{3}')); + }, + + testSubWithReplacementFunction: function() { + var source = 'foo boo boz'; + + this.assertEqual('Foo boo boz', + source.sub(/[^o]+/, function(match) { + return match[0].toUpperCase() + }), 1); + this.assertEqual('Foo Boo boz', + source.sub(/[^o]+/, function(match) { + return match[0].toUpperCase() + }, 2), 2); + this.assertEqual(source, + source.sub(/[^o]+/, function(match) { + return match[0].toUpperCase() + }, 0), 0); + this.assertEqual(source, + source.sub(/[^o]+/, function(match) { + return match[0].toUpperCase() + }, -1), -1); + }, + + testSubWithReplacementString: function() { + var source = 'foo boo boz'; + + this.assertEqual('oo boo boz', + source.sub(/[^o]+/, '')); + this.assertEqual('oooo boz', + source.sub(/[^o]+/, '', 2)); + this.assertEqual('-f-oo boo boz', + source.sub(/[^o]+/, '-#{0}-')); + this.assertEqual('-f-oo- b-oo boz', + source.sub(/[^o]+/, '-#{0}-', 2)); + }, + + testScan: function() { + var source = 'foo boo boz', results = []; + var str = source.scan(/[o]+/, function(match) { + results.push(match[0].length); + }); + this.assertEnumEqual([2, 2, 1], results); + this.assertEqual(source, source.scan(/x/, this.fail)); + this.assert(typeof str == 'string'); + }, + + testToArray: function() { + this.assertEnumEqual([],''.toArray()); + this.assertEnumEqual(['a'],'a'.toArray()); + this.assertEnumEqual(['a','b'],'ab'.toArray()); + this.assertEnumEqual(['f','o','o'],'foo'.toArray()); + }, + + /* + Note that camelize() differs from its Rails counterpart, + as it is optimized for dealing with JavaScript object + properties in conjunction with CSS property names: + - Looks for dashes, not underscores + - CamelCases first word if there is a front dash + */ + testCamelize: function() { + this.assertEqual('', ''.camelize()); + this.assertEqual('', '-'.camelize()); + this.assertEqual('foo', 'foo'.camelize()); + this.assertEqual('foo_bar', 'foo_bar'.camelize()); + this.assertEqual('FooBar', '-foo-bar'.camelize()); + this.assertEqual('FooBar', 'FooBar'.camelize()); + + this.assertEqual('fooBar', 'foo-bar'.camelize()); + this.assertEqual('borderBottomWidth', 'border-bottom-width'.camelize()); + + this.assertEqual('classNameTest','class-name-test'.camelize()); + this.assertEqual('classNameTest','className-test'.camelize()); + this.assertEqual('classNameTest','class-nameTest'.camelize()); + + /* this.benchmark(function(){ + 'class-name-test'.camelize(); + },10000); */ + }, + + testCapitalize: function() { + this.assertEqual('',''.capitalize()); + this.assertEqual('Ä','ä'.capitalize()); + this.assertEqual('A','A'.capitalize()); + this.assertEqual('Hello','hello'.capitalize()); + this.assertEqual('Hello','HELLO'.capitalize()); + this.assertEqual('Hello','Hello'.capitalize()); + this.assertEqual('Hello world','hello WORLD'.capitalize()); + }, + + testUnderscore: function() { + this.assertEqual('', ''.underscore()); + this.assertEqual('_', '-'.underscore()); + this.assertEqual('foo', 'foo'.underscore()); + this.assertEqual('foo', 'Foo'.underscore()); + this.assertEqual('foo_bar', 'foo_bar'.underscore()); + this.assertEqual('border_bottom', 'borderBottom'.underscore()); + this.assertEqual('border_bottom_width', 'borderBottomWidth'.underscore()); + this.assertEqual('border_bottom_width', 'border-Bottom-Width'.underscore()); + }, + + testDasherize: function() { + this.assertEqual('', ''.dasherize()); + this.assertEqual('foo', 'foo'.dasherize()); + this.assertEqual('Foo', 'Foo'.dasherize()); + this.assertEqual('foo-bar', 'foo-bar'.dasherize()); + this.assertEqual('border-bottom-width', 'border_bottom_width'.dasherize()); + }, + + testTruncate: function() { + var source = 'foo boo boz foo boo boz foo boo boz foo boo boz'; + this.assertEqual(source, source.truncate(source.length)); + this.assertEqual('foo boo boz foo boo boz foo...', source.truncate(0)); + this.assertEqual('fo...', source.truncate(5)); + this.assertEqual('foo b', source.truncate(5, '')); + + this.assert(typeof 'foo'.truncate(5) == 'string'); + this.assert(typeof 'foo bar baz'.truncate(5) == 'string'); + }, + + testStrip: function() { + this.assertEqual('hello world', ' hello world '.strip()); + this.assertEqual('hello world', 'hello world'.strip()); + this.assertEqual('hello \n world', ' hello \n world '.strip()); + this.assertEqual('', ' '.strip()); + }, + + testStripTags: function() { + this.assertEqual('hello world', 'hello world'.stripTags()); + this.assertEqual('hello world', 'hello world'.stripTags()); + this.assertEqual('hello world', 'hello world'.stripTags()); + this.assertEqual('hello world', 'hello world'.stripTags()); + this.assertEqual('1\n2', '1\n2'.stripTags()); + }, + + testStripScripts: function() { + this.assertEqual('foo bar', 'foo bar'.stripScripts()); + this.assertEqual('foo bar', ('foo - - - - -

Prototype Unit test file

-

- Test the unit testing library (unittest.js) -

- - -
-
- - -
- -
- - - -
-
- -
  • x1
  • x2
-
  • x1
  • x2
- -
XXXX
- -
testcss1
testcss1
- - - - - diff --git a/test/unit/unittest_test.js b/test/unit/unittest_test.js new file mode 100644 index 0000000..0f79bd4 --- /dev/null +++ b/test/unit/unittest_test.js @@ -0,0 +1,148 @@ +var testObj = { + isNice: function() { + return true; + }, + isBroken: function() { + return false; + } +} + +new Test.Unit.Runner({ + + testIsRunningFromRake: function() { + if (window.location.toString().startsWith('http')) { + this.assert(this.isRunningFromRake); + this.info('These tests are running from rake.') + } else { + this.assert(!this.isRunningFromRake); + this.info('These tests are *not* running from rake.') + } + }, + + testBuildMessage: function() { + this.assertEqual("'foo' 'bar'", this.buildMessage('', '? ?', 'foo', 'bar')) + }, + + testAssertEqual: function() { + this.assertEqual(0, 0); + this.assertEqual(0, 0, "test"); + + this.assertEqual(0,'0'); + this.assertEqual(65.0, 65); + + this.assertEqual("a", "a"); + this.assertEqual("a", "a", "test"); + + this.assertNotEqual(0, 1); + this.assertNotEqual("a","b"); + this.assertNotEqual({},{}); + this.assertNotEqual([],[]); + this.assertNotEqual([],{}); + }, + + testAssertEnumEqual: function() { + this.assertEnumEqual([], []); + this.assertEnumEqual(['a', 'b'], ['a', 'b']); + this.assertEnumEqual(['1', '2'], [1, 2]); + this.assertEnumNotEqual(['1', '2'], [1, 2, 3]); + }, + + testAssertHashEqual: function() { + this.assertHashEqual({}, {}); + this.assertHashEqual({a:'b'}, {a:'b'}); + this.assertHashEqual({a:'b', c:'d'}, {c:'d', a:'b'}); + this.assertHashNotEqual({a:'b', c:'d'}, {c:'d', a:'boo!'}); + }, + + testAssertRespondsTo: function() { + this.assertRespondsTo('isNice', testObj); + this.assertRespondsTo('isBroken', testObj); + }, + + testAssertIdentical: function() { + this.assertIdentical(0, 0); + this.assertIdentical(0, 0, "test"); + this.assertIdentical(1, 1); + this.assertIdentical('a', 'a'); + this.assertIdentical('a', 'a', "test"); + this.assertIdentical('', ''); + this.assertIdentical(undefined, undefined); + this.assertIdentical(null, null); + this.assertIdentical(true, true); + this.assertIdentical(false, false); + + var obj = {a:'b'}; + this.assertIdentical(obj, obj); + + this.assertNotIdentical({1:2,3:4},{1:2,3:4}); + + this.assertIdentical(1, 1.0); // both are typeof == 'number' + + this.assertNotIdentical(1, '1'); + this.assertNotIdentical(1, '1.0'); + }, + + testAssertNullAndAssertUndefined: function() { + this.assertNull(null); + this.assertNotNull(undefined); + this.assertNotNull(0); + this.assertNotNull(''); + this.assertNotUndefined(null); + this.assertUndefined(undefined); + this.assertNotUndefined(0); + this.assertNotUndefined(''); + this.assertNullOrUndefined(null); + this.assertNullOrUndefined(undefined); + this.assertNotNullOrUndefined(0); + this.assertNotNullOrUndefined(''); + }, + + testAssertMatch: function() { + this.assertMatch(/knowmad.jpg$/, 'http://script.aculo.us/images/knowmad.jpg'); + this.assertMatch(/Fuc/, 'Thomas Fuchs'); + this.assertMatch(/^\$(\d{1,3}(\,\d{3})*|(\d+))(\.\d{2})?$/, '$19.95'); + this.assertMatch(/(\d{3}\) ?)|(\d{3}[- \.])?\d{3}[- \.]\d{4}(\s(x\d+)?){0,1}$/, '704-343-9330'); + this.assertMatch(/^(?:(?:(?:(?:(?:1[6-9]|[2-9]\d)?(?:0[48]|[2468][048]|[13579][26])|(?:(?:16|[2468][048]|[3579][26])00)))(\/|-|\.)(?:0?2\1(?:29)))|(?:(?:(?:1[6-9]|[2-9]\d)?\d{2})(\/|-|\.)(?:(?:(?:0?[13578]|1[02])\2(?:31))|(?:(?:0?[1,3-9]|1[0-2])\2(29|30))|(?:(?:0?[1-9])|(?:1[0-2]))\2(?:0?[1-9]|1\d|2[0-8]))))$/, '2001-06-16'); + this.assertMatch(/^((0?[123456789])|(1[012]))\s*:\s*([012345]\d)(\s*:\s*([012345]\d))?\s*[ap]m\s*-\s*((0?[123456789])|(1[012]))\s*:\s*([012345]\d)(\s*:\s*([012345]\d))?\s*[ap]m$/i, '2:00PM-2:15PM'); + this.assertNoMatch(/zubar/, 'foo bar'); + }, + + testAssertInstanceOf: function() { + this.assertInstanceOf(String, new String); + this.assertInstanceOf(RegExp, /foo/); + this.assertNotInstanceOf(String, {}); + }, + + testAssertVisible: function() { + this.assertVisible('testcss1'); + this.assertNotVisible('testcss1_span'); + //this.assertNotVisible('testcss2', "Due to a Safari bug, this test fails in Safari."); + + Element.hide('testcss1'); + this.assertNotVisible('testcss1'); + this.assertNotVisible('testcss1_span'); + Element.show('testcss1'); + this.assertVisible('testcss1'); + this.assertNotVisible('testcss1_span'); + + Element.show('testcss1_span'); + this.assertVisible('testcss1_span'); + Element.hide('testcss1'); + this.assertNotVisible('testcss1_span'); // hidden by parent + }, + + testAssertElementsMatch: function() { + this.assertElementsMatch($$('#tlist'), '#tlist'); + this.assertElementMatches($('tlist'), '#tlist'); + } +}); + +new Test.Unit.Runner({ + testDummy: function() { + this.assert(true); + }, + + testMultipleTestRunner: function() { + this.assertEqual('passed', $('testlog_2').down('td', 1).innerHTML); + } +}, {testLog: 'testlog_2'}); \ No newline at end of file