From 2525b21be24c1bc47aee6ae65c38182110982dcf Mon Sep 17 00:00:00 2001 From: Tobie Langel Date: Thu, 11 Dec 2008 12:06:00 +0100 Subject: [PATCH] Reorganized unit tests to match the file structure of the source. --- .gitignore | 4 +- dist/.gitignore | 3 +- test/unit/class_test.js | 130 +++++++++++++++++++ test/unit/date_test.js | 5 + test/unit/fixtures/class.js | 83 ++++++++++++ test/unit/fixtures/function.js | 13 ++ test/unit/fixtures/object.html | 6 + test/unit/fixtures/object.js | 7 ++ test/unit/function_test.js | 133 ++++++++++++++++++++ test/unit/object_test.js | 174 ++++++++++++++++++++++++++ test/unit/periodical_executer_test.js | 15 +++ test/unit/prototype_test.js | 43 +++++++ test/unit/regexp_test.js | 42 +++++++ 13 files changed, 656 insertions(+), 2 deletions(-) create mode 100644 test/unit/class_test.js create mode 100644 test/unit/date_test.js create mode 100644 test/unit/fixtures/class.js create mode 100644 test/unit/fixtures/function.js create mode 100644 test/unit/fixtures/object.html create mode 100644 test/unit/fixtures/object.js create mode 100644 test/unit/function_test.js create mode 100644 test/unit/object_test.js create mode 100644 test/unit/periodical_executer_test.js create mode 100644 test/unit/prototype_test.js create mode 100644 test/unit/regexp_test.js diff --git a/.gitignore b/.gitignore index 496ee2c..ee3335f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -.DS_Store \ No newline at end of file +.DS_Store +pkg +test/unit/tmp/* \ No newline at end of file diff --git a/dist/.gitignore b/dist/.gitignore index ab1e075..dc3a5c4 100644 --- a/dist/.gitignore +++ b/dist/.gitignore @@ -1 +1,2 @@ -prototype.js \ No newline at end of file +prototype.js +prototype_update_helper.js \ No newline at end of file diff --git a/test/unit/class_test.js b/test/unit/class_test.js new file mode 100644 index 0000000..98e8e88 --- /dev/null +++ b/test/unit/class_test.js @@ -0,0 +1,130 @@ +new Test.Unit.Runner({ + testClassCreate: function() { + this.assert(Object.isFunction(Animal), 'Animal is not a constructor'); + this.assertEnumEqual([Cat, Mouse, Dog, Ox], Animal.subclasses); + Animal.subclasses.each(function(subclass) { + this.assertEqual(Animal, subclass.superclass); + }, this); + + var Bird = Class.create(Animal); + this.assertEqual(Bird, Animal.subclasses.last()); + // for..in loop (for some reason) doesn't iterate over the constructor property in top-level classes + this.assertEnumEqual(Object.keys(new Animal).sort(), Object.keys(new Bird).without('constructor').sort()); + }, + + testClassInstantiation: function() { + var pet = new Animal("Nibbles"); + this.assertEqual("Nibbles", pet.name, "property not initialized"); + this.assertEqual('Nibbles: Hi!', pet.say('Hi!')); + this.assertEqual(Animal, pet.constructor, "bad constructor reference"); + this.assertUndefined(pet.superclass); + + var Empty = Class.create(); + this.assert('object', typeof new Empty); + }, + + testInheritance: function() { + var tom = new Cat('Tom'); + this.assertEqual(Cat, tom.constructor, "bad constructor reference"); + this.assertEqual(Animal, tom.constructor.superclass, 'bad superclass reference'); + this.assertEqual('Tom', tom.name); + this.assertEqual('Tom: meow', tom.say('meow')); + this.assertEqual('Tom: Yuk! I only eat mice.', tom.eat(new Animal)); + }, + + testSuperclassMethodCall: function() { + var tom = new Cat('Tom'); + this.assertEqual('Tom: Yum!', tom.eat(new Mouse)); + + // augment the constructor and test + var Dodo = Class.create(Animal, { + initialize: function($super, name) { + $super(name); + this.extinct = true; + }, + + say: function($super, message) { + return $super(message) + " honk honk"; + } + }); + + var gonzo = new Dodo('Gonzo'); + this.assertEqual('Gonzo', gonzo.name); + this.assert(gonzo.extinct, 'Dodo birds should be extinct'); + this.assertEqual("Gonzo: hello honk honk", gonzo.say("hello")); + }, + + testClassAddMethods: function() { + var tom = new Cat('Tom'); + var jerry = new Mouse('Jerry'); + + Animal.addMethods({ + sleep: function() { + return this.say('ZZZ'); + } + }); + + Mouse.addMethods({ + sleep: function($super) { + return $super() + " ... no, can't sleep! Gotta steal cheese!"; + }, + escape: function(cat) { + return this.say('(from a mousehole) Take that, ' + cat.name + '!'); + } + }); + + this.assertEqual('Tom: ZZZ', tom.sleep(), "added instance method not available to subclass"); + this.assertEqual("Jerry: ZZZ ... no, can't sleep! Gotta steal cheese!", jerry.sleep()); + this.assertEqual("Jerry: (from a mousehole) Take that, Tom!", jerry.escape(tom)); + // insure that a method has not propagated *up* the prototype chain: + this.assertUndefined(tom.escape); + this.assertUndefined(new Animal().escape); + + Animal.addMethods({ + sleep: function() { + return this.say('zZzZ'); + } + }); + + this.assertEqual("Jerry: zZzZ ... no, can't sleep! Gotta steal cheese!", jerry.sleep()); + }, + + testBaseClassWithMixin: function() { + var grass = new Plant('grass', 3); + this.assertRespondsTo('getValue', grass); + this.assertEqual('#', grass.inspect()); + }, + + testSubclassWithMixin: function() { + var snoopy = new Dog('Snoopy', 12, 'male'); + this.assertRespondsTo('reproduce', snoopy); + }, + + testSubclassWithMixins: function() { + var cow = new Ox('cow', 400, 'female'); + this.assertEqual('#', cow.inspect()); + this.assertRespondsTo('reproduce', cow); + this.assertRespondsTo('getValue', cow); + }, + + testClassWithToStringAndValueOfMethods: function() { + var Foo = Class.create({ + toString: function() { return "toString" }, + valueOf: function() { return "valueOf" } + }); + + var Parent = Class.create({ + m1: function(){ return 'm1' }, + m2: function(){ return 'm2' } + }); + var Child = Class.create(Parent, { + m1: function($super) { return 'm1 child' }, + m2: function($super) { return 'm2 child' } + }); + + this.assert(new Child().m1.toString().indexOf('m1 child') > -1); + + this.assertEqual("toString", new Foo().toString()); + this.assertEqual("valueOf", new Foo().valueOf()); + } +}); \ No newline at end of file diff --git a/test/unit/date_test.js b/test/unit/date_test.js new file mode 100644 index 0000000..6cd68c3 --- /dev/null +++ b/test/unit/date_test.js @@ -0,0 +1,5 @@ +new Test.Unit.Runner({ + testDateToJSON: function() { + this.assertEqual('\"1970-01-01T00:00:00Z\"', new Date(Date.UTC(1970, 0, 1)).toJSON()); + } +}); \ No newline at end of file diff --git a/test/unit/fixtures/class.js b/test/unit/fixtures/class.js new file mode 100644 index 0000000..91947f8 --- /dev/null +++ b/test/unit/fixtures/class.js @@ -0,0 +1,83 @@ +// base class +var Animal = Class.create({ + initialize: function(name) { + this.name = name; + }, + name: "", + eat: function() { + return this.say("Yum!"); + }, + say: function(message) { + return this.name + ": " + message; + } +}); + +// subclass that augments a method +var Cat = Class.create(Animal, { + eat: function($super, food) { + if (food instanceof Mouse) return $super(); + else return this.say("Yuk! I only eat mice."); + } +}); + +// empty subclass +var Mouse = Class.create(Animal, {}); + +//mixins +var Sellable = { + getValue: function(pricePerKilo) { + return this.weight * pricePerKilo; + }, + + inspect: function() { + return '#'.interpolate(this); + } +}; + +var Reproduceable = { + reproduce: function(partner) { + if (partner.constructor != this.constructor || partner.sex == this.sex) + return null; + var weight = this.weight / 10, sex = Math.random(1).round() ? 'male' : 'female'; + return new this.constructor('baby', weight, sex); + } +}; + +// base class with mixin +var Plant = Class.create(Sellable, { + initialize: function(name, weight) { + this.name = name; + this.weight = weight; + }, + + inspect: function() { + return '#'.interpolate(this); + } +}); + +// subclass with mixin +var Dog = Class.create(Animal, Reproduceable, { + initialize: function($super, name, weight, sex) { + this.weight = weight; + this.sex = sex; + $super(name); + } +}); + +// subclass with mixins +var Ox = Class.create(Animal, Sellable, Reproduceable, { + initialize: function($super, name, weight, sex) { + this.weight = weight; + this.sex = sex; + $super(name); + }, + + eat: function(food) { + if (food instanceof Plant) + this.weight += food.weight; + }, + + inspect: function() { + return '#'.interpolate(this); + } +}); \ No newline at end of file diff --git a/test/unit/fixtures/function.js b/test/unit/fixtures/function.js new file mode 100644 index 0000000..d88f76c --- /dev/null +++ b/test/unit/fixtures/function.js @@ -0,0 +1,13 @@ +var arg1 = 1; +var arg2 = 2; +var arg3 = 3; +function TestObj() { }; +TestObj.prototype.assertingEventHandler = + function(event, assertEvent, assert1, assert2, assert3, a1, a2, a3) { + assertEvent(event); + assert1(a1); + assert2(a2); + assert3(a3); + }; + +var globalBindTest = null; diff --git a/test/unit/fixtures/object.html b/test/unit/fixtures/object.html new file mode 100644 index 0000000..5a08fbd --- /dev/null +++ b/test/unit/fixtures/object.html @@ -0,0 +1,6 @@ +
+
    +
  • +
  • +
  • +
\ No newline at end of file diff --git a/test/unit/fixtures/object.js b/test/unit/fixtures/object.js new file mode 100644 index 0000000..2526bea --- /dev/null +++ b/test/unit/fixtures/object.js @@ -0,0 +1,7 @@ +var Person = function(name){ + this.name = name; +}; + +Person.prototype.toJSON = function() { + return '-' + this.name; +}; \ No newline at end of file diff --git a/test/unit/function_test.js b/test/unit/function_test.js new file mode 100644 index 0000000..2a9e8b2 --- /dev/null +++ b/test/unit/function_test.js @@ -0,0 +1,133 @@ +new Test.Unit.Runner({ + testFunctionArgumentNames: function() { + this.assertEnumEqual([], (function() {}).argumentNames()); + this.assertEnumEqual(["one"], (function(one) {}).argumentNames()); + this.assertEnumEqual(["one", "two", "three"], (function(one, two, three) {}).argumentNames()); + this.assertEnumEqual(["one", "two", "three"], (function( one , two + , three ) {}).argumentNames()); + this.assertEqual("$super", (function($super) {}).argumentNames().first()); + + function named1() {}; + this.assertEnumEqual([], named1.argumentNames()); + function named2(one) {}; + this.assertEnumEqual(["one"], named2.argumentNames()); + function named3(one, two, three) {}; + this.assertEnumEqual(["one", "two", "three"], named3.argumentNames()); + function named4(one, + two, + + three) {} + this.assertEnumEqual($w('one two three'), named4.argumentNames()); + function named5(/*foo*/ foo, /* bar */ bar, /*****/ baz) {} + this.assertEnumEqual($w("foo bar baz"), named5.argumentNames()); + function named6( + /*foo*/ foo, + /**/bar, + /* baz */ /* baz */ baz, + // Skip a line just to screw with the regex... + /* thud */ thud) {} + this.assertEnumEqual($w("foo bar baz thud"), named6.argumentNames()); + }, + + testFunctionBind: function() { + function methodWithoutArguments() { return this.hi }; + function methodWithArguments() { return this.hi + ',' + $A(arguments).join(',') }; + var func = Prototype.emptyFunction; + + this.assertIdentical(func, func.bind()); + this.assertIdentical(func, func.bind(undefined)); + this.assertNotIdentical(func, func.bind(null)); + + this.assertEqual('without', methodWithoutArguments.bind({ hi: 'without' })()); + this.assertEqual('with,arg1,arg2', methodWithArguments.bind({ hi: 'with' })('arg1','arg2')); + this.assertEqual('withBindArgs,arg1,arg2', + methodWithArguments.bind({ hi: 'withBindArgs' }, 'arg1', 'arg2')()); + this.assertEqual('withBindArgsAndArgs,arg1,arg2,arg3,arg4', + methodWithArguments.bind({ hi: 'withBindArgsAndArgs' }, 'arg1', 'arg2')('arg3', 'arg4')); + }, + + testFunctionCurry: function() { + var split = function(delimiter, string) { return string.split(delimiter); }; + var splitOnColons = split.curry(":"); + this.assertNotIdentical(split, splitOnColons); + this.assertEnumEqual(split(":", "0:1:2:3:4:5"), splitOnColons("0:1:2:3:4:5")); + this.assertIdentical(split, split.curry()); + }, + + testFunctionDelay: function() { + window.delayed = undefined; + var delayedFunction = function() { window.delayed = true; }; + var delayedFunctionWithArgs = function() { window.delayedWithArgs = $A(arguments).join(' '); }; + delayedFunction.delay(0.8); + delayedFunctionWithArgs.delay(0.8, 'hello', 'world'); + this.assertUndefined(window.delayed); + this.wait(1000, function() { + this.assert(window.delayed); + this.assertEqual('hello world', window.delayedWithArgs); + }); + }, + + testFunctionWrap: function() { + function sayHello(){ + return 'hello world'; + }; + + this.assertEqual('HELLO WORLD', sayHello.wrap(function(proceed) { + return proceed().toUpperCase(); + })()); + + var temp = String.prototype.capitalize; + String.prototype.capitalize = String.prototype.capitalize.wrap(function(proceed, eachWord) { + if(eachWord && this.include(' ')) return this.split(' ').map(function(str){ + return str.capitalize(); + }).join(' '); + return proceed(); + }); + this.assertEqual('Hello world', 'hello world'.capitalize()); + this.assertEqual('Hello World', 'hello world'.capitalize(true)); + this.assertEqual('Hello', 'hello'.capitalize()); + String.prototype.capitalize = temp; + }, + + testFunctionDefer: function() { + window.deferred = undefined; + var deferredFunction = function() { window.deferred = true; }; + deferredFunction.defer(); + this.assertUndefined(window.deferred); + this.wait(50, function() { + this.assert(window.deferred); + + window.deferredValue = 0; + var deferredFunction2 = function(arg) { window.deferredValue = arg; }; + deferredFunction2.defer('test'); + this.wait(50, function() { + this.assertEqual('test', window.deferredValue); + }); + }); + }, + + testFunctionMethodize: function() { + var Foo = { bar: function(baz) { return baz } }; + var baz = { quux: Foo.bar.methodize() }; + + this.assertEqual(Foo.bar.methodize(), baz.quux); + this.assertEqual(baz, Foo.bar(baz)); + this.assertEqual(baz, baz.quux()); + }, + + testBindAsEventListener: function() { + for( var i = 0; i < 10; ++i ){ + var div = document.createElement('div'); + div.setAttribute('id','test-'+i); + document.body.appendChild(div); + var tobj = new TestObj(); + var eventTest = { test: true }; + var call = tobj.assertingEventHandler.bindAsEventListener(tobj, + this.assertEqual.bind(this, eventTest), + this.assertEqual.bind(this, arg1), + this.assertEqual.bind(this, arg2), + this.assertEqual.bind(this, arg3), arg1, arg2, arg3 ); + call(eventTest); + } + } +}); \ No newline at end of file diff --git a/test/unit/object_test.js b/test/unit/object_test.js new file mode 100644 index 0000000..46fa047 --- /dev/null +++ b/test/unit/object_test.js @@ -0,0 +1,174 @@ +new Test.Unit.Runner({ + testObjectExtend: function() { + var object = {foo: 'foo', bar: [1, 2, 3]}; + this.assertIdentical(object, Object.extend(object)); + this.assertHashEqual({foo: 'foo', bar: [1, 2, 3]}, object); + this.assertIdentical(object, Object.extend(object, {bla: 123})); + this.assertHashEqual({foo: 'foo', bar: [1, 2, 3], bla: 123}, object); + this.assertHashEqual({foo: 'foo', bar: [1, 2, 3], bla: null}, + Object.extend(object, {bla: null})); + }, + + testObjectToQueryString: function() { + this.assertEqual('a=A&b=B&c=C&d=D%23', Object.toQueryString({a: 'A', b: 'B', c: 'C', d: 'D#'})); + }, + + testObjectClone: function() { + var object = {foo: 'foo', bar: [1, 2, 3]}; + this.assertNotIdentical(object, Object.clone(object)); + this.assertHashEqual(object, Object.clone(object)); + this.assertHashEqual({}, Object.clone()); + var clone = Object.clone(object); + delete clone.bar; + this.assertHashEqual({foo: 'foo'}, clone, + "Optimizing Object.clone perf using prototyping doesn't allow properties to be deleted."); + }, + + testObjectInspect: function() { + this.assertEqual('undefined', Object.inspect()); + this.assertEqual('undefined', Object.inspect(undefined)); + this.assertEqual('null', Object.inspect(null)); + this.assertEqual("'foo\\\\b\\\'ar'", Object.inspect('foo\\b\'ar')); + this.assertEqual('[]', Object.inspect([])); + this.assertNothingRaised(function() { Object.inspect(window.Node) }); + }, + + testObjectToJSON: function() { + this.assertUndefined(Object.toJSON(undefined)); + this.assertUndefined(Object.toJSON(Prototype.K)); + this.assertEqual('\"\"', Object.toJSON('')); + this.assertEqual('[]', Object.toJSON([])); + this.assertEqual('[\"a\"]', Object.toJSON(['a'])); + this.assertEqual('[\"a\", 1]', Object.toJSON(['a', 1])); + this.assertEqual('[\"a\", {\"b\": null}]', Object.toJSON(['a', {'b': null}])); + this.assertEqual('{\"a\": \"hello!\"}', Object.toJSON({a: 'hello!'})); + this.assertEqual('{}', Object.toJSON({})); + this.assertEqual('{}', Object.toJSON({a: undefined, b: undefined, c: Prototype.K})); + this.assertEqual('{\"b\": [false, true], \"c\": {\"a\": \"hello!\"}}', + Object.toJSON({'b': [undefined, false, true, undefined], c: {a: 'hello!'}})); + this.assertEqual('{\"b\": [false, true], \"c\": {\"a\": \"hello!\"}}', + Object.toJSON($H({'b': [undefined, false, true, undefined], c: {a: 'hello!'}}))); + this.assertEqual('true', Object.toJSON(true)); + this.assertEqual('false', Object.toJSON(false)); + this.assertEqual('null', Object.toJSON(null)); + var sam = new Person('sam'); + this.assertEqual('-sam', Object.toJSON(sam)); + this.assertEqual('-sam', sam.toJSON()); + var element = $('test'); + this.assertUndefined(Object.toJSON(element)); + element.toJSON = function(){return 'I\'m a div with id test'}; + this.assertEqual('I\'m a div with id test', Object.toJSON(element)); + }, + + testObjectToHTML: function() { + this.assertIdentical('', Object.toHTML()); + this.assertIdentical('', Object.toHTML('')); + this.assertIdentical('', Object.toHTML(null)); + this.assertIdentical('0', Object.toHTML(0)); + this.assertIdentical('123', Object.toHTML(123)); + this.assertEqual('hello world', Object.toHTML('hello world')); + this.assertEqual('hello world', Object.toHTML({toHTML: function() { return 'hello world' }})); + }, + + testObjectIsArray: function() { + this.assert(Object.isArray([])); + this.assert(Object.isArray([0])); + this.assert(Object.isArray([0, 1])); + this.assert(!Object.isArray({})); + this.assert(!Object.isArray($('list').childNodes)); + this.assert(!Object.isArray()); + this.assert(!Object.isArray('')); + this.assert(!Object.isArray('foo')); + this.assert(!Object.isArray(0)); + this.assert(!Object.isArray(1)); + this.assert(!Object.isArray(null)); + this.assert(!Object.isArray(true)); + this.assert(!Object.isArray(false)); + this.assert(!Object.isArray(undefined)); + }, + + testObjectIsHash: function() { + this.assert(Object.isHash($H())); + this.assert(Object.isHash(new Hash())); + this.assert(!Object.isHash({})); + this.assert(!Object.isHash(null)); + this.assert(!Object.isHash()); + this.assert(!Object.isHash('')); + this.assert(!Object.isHash(2)); + this.assert(!Object.isHash(false)); + this.assert(!Object.isHash(true)); + this.assert(!Object.isHash([])); + }, + + testObjectIsElement: function() { + this.assert(Object.isElement(document.createElement('div'))); + this.assert(Object.isElement(new Element('div'))); + this.assert(Object.isElement($('testlog'))); + this.assert(!Object.isElement(document.createTextNode('bla'))); + + // falsy variables should not mess up return value type + this.assertIdentical(false, Object.isElement(0)); + this.assertIdentical(false, Object.isElement('')); + this.assertIdentical(false, Object.isElement(NaN)); + this.assertIdentical(false, Object.isElement(null)); + this.assertIdentical(false, Object.isElement(undefined)); + }, + + testObjectIsFunction: function() { + this.assert(Object.isFunction(function() { })); + this.assert(Object.isFunction(Class.create())); + this.assert(!Object.isFunction("a string")); + this.assert(!Object.isFunction($("testlog"))); + this.assert(!Object.isFunction([])); + this.assert(!Object.isFunction({})); + this.assert(!Object.isFunction(0)); + this.assert(!Object.isFunction(false)); + this.assert(!Object.isFunction(undefined)); + }, + + testObjectIsString: function() { + this.assert(!Object.isString(function() { })); + this.assert(Object.isString("a string")); + this.assert(!Object.isString(0)); + this.assert(!Object.isString([])); + this.assert(!Object.isString({})); + this.assert(!Object.isString(false)); + this.assert(!Object.isString(undefined)); + }, + + testObjectIsNumber: function() { + this.assert(Object.isNumber(0)); + this.assert(Object.isNumber(1.0)); + this.assert(!Object.isNumber(function() { })); + this.assert(!Object.isNumber("a string")); + this.assert(!Object.isNumber([])); + this.assert(!Object.isNumber({})); + this.assert(!Object.isNumber(false)); + this.assert(!Object.isNumber(undefined)); + }, + + testObjectIsUndefined: function() { + this.assert(Object.isUndefined(undefined)); + this.assert(!Object.isUndefined(null)); + this.assert(!Object.isUndefined(false)); + this.assert(!Object.isUndefined(0)); + this.assert(!Object.isUndefined("")); + this.assert(!Object.isUndefined(function() { })); + this.assert(!Object.isUndefined([])); + this.assert(!Object.isUndefined({})); + }, + + // sanity check + testDoesntExtendObjectPrototype: function() { + // for-in is supported with objects + var iterations = 0, obj = { a: 1, b: 2, c: 3 }; + for(property in obj) iterations++; + this.assertEqual(3, iterations); + + // for-in is not supported with arrays + iterations = 0; + var arr = [1,2,3]; + for(property in arr) iterations++; + this.assert(iterations > 3); + } +}); \ No newline at end of file diff --git a/test/unit/periodical_executer_test.js b/test/unit/periodical_executer_test.js new file mode 100644 index 0000000..9640b33 --- /dev/null +++ b/test/unit/periodical_executer_test.js @@ -0,0 +1,15 @@ +new Test.Unit.Runner({ + testPeriodicalExecuterStop: function() { + var peEventCount = 0; + function peEventFired(pe) { + if (++peEventCount > 2) pe.stop(); + } + + // peEventFired will stop the PeriodicalExecuter after 3 callbacks + new PeriodicalExecuter(peEventFired, 0.05); + + this.wait(600, function() { + this.assertEqual(3, peEventCount); + }); + } +}); \ No newline at end of file diff --git a/test/unit/prototype_test.js b/test/unit/prototype_test.js new file mode 100644 index 0000000..be3cbb3 --- /dev/null +++ b/test/unit/prototype_test.js @@ -0,0 +1,43 @@ +new Test.Unit.Runner({ + testBrowserDetection: function() { + var results = $H(Prototype.Browser).map(function(engine){ + return engine; + }).partition(function(engine){ + return engine[1] === true + }); + var trues = results[0], falses = results[1]; + + this.info('User agent string is: ' + navigator.userAgent); + + this.assert(trues.size() == 0 || trues.size() == 1, + 'There should be only one or no browser detected.'); + + // we should have definite trues or falses here + trues.each(function(result) { + this.assert(result[1] === true); + }, this); + falses.each(function(result) { + this.assert(result[1] === false); + }, this); + + if(navigator.userAgent.indexOf('AppleWebKit/') > -1) { + this.info('Running on WebKit'); + this.assert(Prototype.Browser.WebKit); + } + + if(!!window.opera) { + this.info('Running on Opera'); + this.assert(Prototype.Browser.Opera); + } + + if(!!(window.attachEvent && !window.opera)) { + this.info('Running on IE'); + this.assert(Prototype.Browser.IE); + } + + if(navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('KHTML') == -1) { + this.info('Running on Gecko'); + this.assert(Prototype.Browser.Gecko); + } + } +}); \ No newline at end of file diff --git a/test/unit/regexp_test.js b/test/unit/regexp_test.js new file mode 100644 index 0000000..9aadcd7 --- /dev/null +++ b/test/unit/regexp_test.js @@ -0,0 +1,42 @@ +new Test.Unit.Runner({ + testRegExpEscape: function() { + this.assertEqual('word', RegExp.escape('word')); + this.assertEqual('\\/slashes\\/', RegExp.escape('/slashes/')); + this.assertEqual('\\\\backslashes\\\\', RegExp.escape('\\backslashes\\')); + this.assertEqual('\\\\border of word', RegExp.escape('\\border of word')); + + this.assertEqual('\\(\\?\\:non-capturing\\)', RegExp.escape('(?:non-capturing)')); + this.assertEqual('non-capturing', new RegExp(RegExp.escape('(?:') + '([^)]+)').exec('(?:non-capturing)')[1]); + + this.assertEqual('\\(\\?\\=positive-lookahead\\)', RegExp.escape('(?=positive-lookahead)')); + this.assertEqual('positive-lookahead', new RegExp(RegExp.escape('(?=') + '([^)]+)').exec('(?=positive-lookahead)')[1]); + + this.assertEqual('\\(\\?<\\=positive-lookbehind\\)', RegExp.escape('(?<=positive-lookbehind)')); + this.assertEqual('positive-lookbehind', new RegExp(RegExp.escape('(?<=') + '([^)]+)').exec('(?<=positive-lookbehind)')[1]); + + this.assertEqual('\\(\\?\\!negative-lookahead\\)', RegExp.escape('(?!negative-lookahead)')); + this.assertEqual('negative-lookahead', new RegExp(RegExp.escape('(?!') + '([^)]+)').exec('(?!negative-lookahead)')[1]); + + this.assertEqual('\\(\\?<\\!negative-lookbehind\\)', RegExp.escape('(?', new RegExp(RegExp.escape('
')).exec('
')[0]); + + this.assertEqual('false', RegExp.escape(false)); + this.assertEqual('undefined', RegExp.escape()); + this.assertEqual('null', RegExp.escape(null)); + this.assertEqual('42', RegExp.escape(42)); + + this.assertEqual('\\\\n\\\\r\\\\t', RegExp.escape('\\n\\r\\t')); + this.assertEqual('\n\r\t', RegExp.escape('\n\r\t')); + this.assertEqual('\\{5,2\\}', RegExp.escape('{5,2}')); + + this.assertEqual( + '\\/\\(\\[\\.\\*\\+\\?\\^\\=\\!\\:\\$\\{\\}\\(\\)\\|\\[\\\\\\]\\\\\\\/\\\\\\\\\\]\\)\\/g', + RegExp.escape('/([.*+?^=!:${}()|[\\]\\/\\\\])/g') + ); + } +}); \ No newline at end of file