lady_josephine 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/Rakefile +32 -0
- data/app/assets/fonts/lady_josephine/icons/icons.eot +0 -0
- data/app/assets/fonts/lady_josephine/icons/icons.svg +215 -0
- data/app/assets/fonts/lady_josephine/icons/icons.ttf +0 -0
- data/app/assets/fonts/lady_josephine/icons/icons.woff +0 -0
- data/app/assets/javascripts/lady_josephine/blocks/facebook.js +25 -0
- data/app/assets/javascripts/lady_josephine/blocks/instagram.js +22 -0
- data/app/assets/javascripts/lady_josephine/blocks/soundcloud.js +24 -0
- data/app/assets/javascripts/lady_josephine/blocks/twitter.js +25 -0
- data/app/assets/javascripts/lady_josephine/blocks/vimeo.js +55 -0
- data/app/assets/javascripts/lady_josephine/blocks/youtube.js +64 -0
- data/app/assets/javascripts/lady_josephine/editor.js +40 -0
- data/app/assets/javascripts/lady_josephine/lady_josephine.js +4 -0
- data/app/assets/javascripts/lady_josephine/lady_josephine_view.js +6 -0
- data/app/assets/stylesheets/lady_josephine/content.sass +33 -0
- data/app/assets/stylesheets/lady_josephine/icons.sass +175 -0
- data/app/assets/stylesheets/lady_josephine/lady_josephine.sass +6 -0
- data/app/assets/stylesheets/lady_josephine/sir_trevor.sass +619 -0
- data/app/assets/stylesheets/lady_josephine/vars.sass +36 -0
- data/app/controllers/lady_josephine/application_controller.rb +4 -0
- data/app/controllers/lady_josephine/editor_controller.rb +40 -0
- data/app/controllers/lady_josephine/images_controller.rb +26 -0
- data/app/helpers/lady_josephine/helper.rb +25 -0
- data/app/helpers/lady_josephine/sir_trevor_helper.rb +172 -0
- data/app/models/lady_josephine/concerns/model.rb +29 -0
- data/app/models/lady_josephine/concerns/pingable.rb +28 -0
- data/app/models/lady_josephine/concerns/server_uuid.rb +24 -0
- data/app/models/lady_josephine/concerns/sir_trevor_images.rb +38 -0
- data/app/models/lady_josephine/image.rb +41 -0
- data/app/uploader/lady_josephine/base_uploader.rb +47 -0
- data/app/uploader/lady_josephine/image_uploader.rb +149 -0
- data/app/views/lady_josephine/blocks/_audio_block.haml +2 -0
- data/app/views/lady_josephine/blocks/_definition_block.haml +4 -0
- data/app/views/lady_josephine/blocks/_divider_block.haml +2 -0
- data/app/views/lady_josephine/blocks/_extended_image_block.haml +63 -0
- data/app/views/lady_josephine/blocks/_extended_quote_block.haml +5 -0
- data/app/views/lady_josephine/blocks/_extended_tweet_block.haml +2 -0
- data/app/views/lady_josephine/blocks/_facebook_post_block.haml +2 -0
- data/app/views/lady_josephine/blocks/_heading_block.haml +2 -0
- data/app/views/lady_josephine/blocks/_html_block.haml +1 -0
- data/app/views/lady_josephine/blocks/_instagram_block.haml +2 -0
- data/app/views/lady_josephine/blocks/_list_block.haml +3 -0
- data/app/views/lady_josephine/blocks/_quote_block.haml +5 -0
- data/app/views/lady_josephine/blocks/_text_block.html.haml +2 -0
- data/app/views/lady_josephine/blocks/_video_block.haml +9 -0
- data/config/routes.rb +9 -0
- data/db/migrate/20160222151500_lady_josephine_image.rb +18 -0
- data/lib/generators/lady_josephine_migration/USAGE +9 -0
- data/lib/generators/lady_josephine_migration/lady_josephine_migration_generator.rb +17 -0
- data/lib/generators/lady_josephine_migration/templates/migration.rb +9 -0
- data/lib/lady_josephine.rb +18 -0
- data/lib/lady_josephine/engine.rb +18 -0
- data/lib/lady_josephine/redcarpet/custom_markdown_formatter.rb +63 -0
- data/lib/lady_josephine/renderer/sir_trevor_renderer.rb +16 -0
- data/lib/lady_josephine/version.rb +3 -0
- data/lib/lady_josephine/whitelist.rb +26 -0
- data/lib/tasks/lady_josephine_tasks.rake +4 -0
- data/spec/controllers/lady_josephine/editor_controller_spec.rb +58 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +13 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +4 -0
- data/spec/dummy/bin/rake +4 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +26 -0
- data/spec/dummy/config/boot.rb +5 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +4 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/schema.rb +16 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/bla +0 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/spec_helper.rb +17 -0
- data/vendor/assets/components/Eventable/README.md +12 -0
- data/vendor/assets/components/Eventable/bower.json +10 -0
- data/vendor/assets/components/Eventable/component.json +11 -0
- data/vendor/assets/components/Eventable/eventable.js +207 -0
- data/vendor/assets/components/Eventable/package.json +15 -0
- data/vendor/assets/components/jquery-autosize/bower.json +30 -0
- data/vendor/assets/components/jquery-autosize/demo.html +36 -0
- data/vendor/assets/components/jquery-autosize/jquery.autosize.js +273 -0
- data/vendor/assets/components/jquery-autosize/jquery.autosize.min.js +6 -0
- data/vendor/assets/components/jquery-autosize/package.json +32 -0
- data/vendor/assets/components/jquery-autosize/readme.md +216 -0
- data/vendor/assets/components/jquery/AUTHORS.txt +163 -0
- data/vendor/assets/components/jquery/CONTRIBUTING.md +216 -0
- data/vendor/assets/components/jquery/Gruntfile.js +496 -0
- data/vendor/assets/components/jquery/MIT-LICENSE.txt +21 -0
- data/vendor/assets/components/jquery/README.md +415 -0
- data/vendor/assets/components/jquery/build/release-notes.js +59 -0
- data/vendor/assets/components/jquery/build/release.js +246 -0
- data/vendor/assets/components/jquery/component.json +13 -0
- data/vendor/assets/components/jquery/composer.json +35 -0
- data/vendor/assets/components/jquery/jquery-migrate.js +496 -0
- data/vendor/assets/components/jquery/jquery-migrate.min.js +3 -0
- data/vendor/assets/components/jquery/jquery.js +9597 -0
- data/vendor/assets/components/jquery/jquery.min.js +5 -0
- data/vendor/assets/components/jquery/jquery.min.map +1 -0
- data/vendor/assets/components/jquery/package.json +39 -0
- data/vendor/assets/components/jquery/speed/benchmark.js +15 -0
- data/vendor/assets/components/jquery/speed/benchmarker.css +65 -0
- data/vendor/assets/components/jquery/speed/benchmarker.js +181 -0
- data/vendor/assets/components/jquery/speed/closest.html +39 -0
- data/vendor/assets/components/jquery/speed/css.html +82 -0
- data/vendor/assets/components/jquery/speed/event.html +58 -0
- data/vendor/assets/components/jquery/speed/filter.html +183 -0
- data/vendor/assets/components/jquery/speed/find.html +179 -0
- data/vendor/assets/components/jquery/speed/index.html +72 -0
- data/vendor/assets/components/jquery/speed/jquery-basis.js +6238 -0
- data/vendor/assets/components/jquery/speed/slice.vs.concat.html +47 -0
- data/vendor/assets/components/jquery/src/ajax.js +851 -0
- data/vendor/assets/components/jquery/src/ajax/jsonp.js +80 -0
- data/vendor/assets/components/jquery/src/ajax/script.js +86 -0
- data/vendor/assets/components/jquery/src/ajax/xhr.js +207 -0
- data/vendor/assets/components/jquery/src/attributes.js +661 -0
- data/vendor/assets/components/jquery/src/callbacks.js +196 -0
- data/vendor/assets/components/jquery/src/core.js +949 -0
- data/vendor/assets/components/jquery/src/css.js +679 -0
- data/vendor/assets/components/jquery/src/data.js +340 -0
- data/vendor/assets/components/jquery/src/deferred.js +141 -0
- data/vendor/assets/components/jquery/src/deprecated.js +4 -0
- data/vendor/assets/components/jquery/src/dimensions.js +41 -0
- data/vendor/assets/components/jquery/src/effects.js +730 -0
- data/vendor/assets/components/jquery/src/event-alias.js +15 -0
- data/vendor/assets/components/jquery/src/event.js +991 -0
- data/vendor/assets/components/jquery/src/exports.js +18 -0
- data/vendor/assets/components/jquery/src/intro.js +20 -0
- data/vendor/assets/components/jquery/src/manipulation.js +796 -0
- data/vendor/assets/components/jquery/src/offset.js +169 -0
- data/vendor/assets/components/jquery/src/outro.js +2 -0
- data/vendor/assets/components/jquery/src/queue.js +147 -0
- data/vendor/assets/components/jquery/src/serialize.js +99 -0
- data/vendor/assets/components/jquery/src/sizzle-jquery.js +9 -0
- data/vendor/assets/components/jquery/src/support.js +241 -0
- data/vendor/assets/components/jquery/src/traversing.js +275 -0
- data/vendor/assets/components/jquery/test/csp.php +16 -0
- data/vendor/assets/components/jquery/test/data/1x1.jpg +0 -0
- data/vendor/assets/components/jquery/test/data/ajax/unreleasedXHR.html +25 -0
- data/vendor/assets/components/jquery/test/data/atom+xml.php +4 -0
- data/vendor/assets/components/jquery/test/data/badcall.js +1 -0
- data/vendor/assets/components/jquery/test/data/badjson.js +1 -0
- data/vendor/assets/components/jquery/test/data/cleanScript.html +10 -0
- data/vendor/assets/components/jquery/test/data/core/cc_on.html +22 -0
- data/vendor/assets/components/jquery/test/data/dashboard.xml +11 -0
- data/vendor/assets/components/jquery/test/data/dimensions/documentLarge.html +17 -0
- data/vendor/assets/components/jquery/test/data/dimensions/documentSmall.html +21 -0
- data/vendor/assets/components/jquery/test/data/echoData.php +1 -0
- data/vendor/assets/components/jquery/test/data/echoQuery.php +1 -0
- data/vendor/assets/components/jquery/test/data/errorWithText.php +5 -0
- data/vendor/assets/components/jquery/test/data/etag.php +21 -0
- data/vendor/assets/components/jquery/test/data/evalScript.php +1 -0
- data/vendor/assets/components/jquery/test/data/event/longLoadScript.php +4 -0
- data/vendor/assets/components/jquery/test/data/event/promiseReady.html +17 -0
- data/vendor/assets/components/jquery/test/data/event/syncReady.html +23 -0
- data/vendor/assets/components/jquery/test/data/headers.php +18 -0
- data/vendor/assets/components/jquery/test/data/if_modified_since.php +20 -0
- data/vendor/assets/components/jquery/test/data/iframe.html +8 -0
- data/vendor/assets/components/jquery/test/data/jquery-1.8.2.ajax_xhr.min.js +2 -0
- data/vendor/assets/components/jquery/test/data/json.php +13 -0
- data/vendor/assets/components/jquery/test/data/json_obj.js +1 -0
- data/vendor/assets/components/jquery/test/data/jsonp.php +14 -0
- data/vendor/assets/components/jquery/test/data/manipulation/iframe-denied.html +36 -0
- data/vendor/assets/components/jquery/test/data/name.html +1 -0
- data/vendor/assets/components/jquery/test/data/name.php +24 -0
- data/vendor/assets/components/jquery/test/data/nocontent.php +5 -0
- data/vendor/assets/components/jquery/test/data/offset/absolute.html +41 -0
- data/vendor/assets/components/jquery/test/data/offset/body.html +26 -0
- data/vendor/assets/components/jquery/test/data/offset/fixed.html +34 -0
- data/vendor/assets/components/jquery/test/data/offset/relative.html +31 -0
- data/vendor/assets/components/jquery/test/data/offset/scroll.html +39 -0
- data/vendor/assets/components/jquery/test/data/offset/static.html +31 -0
- data/vendor/assets/components/jquery/test/data/offset/table.html +43 -0
- data/vendor/assets/components/jquery/test/data/params_html.php +12 -0
- data/vendor/assets/components/jquery/test/data/readywaitasset.js +1 -0
- data/vendor/assets/components/jquery/test/data/readywaitloader.js +25 -0
- data/vendor/assets/components/jquery/test/data/script.php +11 -0
- data/vendor/assets/components/jquery/test/data/selector/html5_selector.html +114 -0
- data/vendor/assets/components/jquery/test/data/selector/sizzle_cache.html +21 -0
- data/vendor/assets/components/jquery/test/data/statusText.php +5 -0
- data/vendor/assets/components/jquery/test/data/support/bodyBackground.html +28 -0
- data/vendor/assets/components/jquery/test/data/support/shrinkWrapBlocks.html +23 -0
- data/vendor/assets/components/jquery/test/data/support/testElementCrash.html +17 -0
- data/vendor/assets/components/jquery/test/data/test.html +7 -0
- data/vendor/assets/components/jquery/test/data/test.js +3 -0
- data/vendor/assets/components/jquery/test/data/test.php +7 -0
- data/vendor/assets/components/jquery/test/data/test2.html +5 -0
- data/vendor/assets/components/jquery/test/data/test3.html +3 -0
- data/vendor/assets/components/jquery/test/data/testinit.js +269 -0
- data/vendor/assets/components/jquery/test/data/testrunner.js +368 -0
- data/vendor/assets/components/jquery/test/data/testsuite.css +155 -0
- data/vendor/assets/components/jquery/test/data/text.php +12 -0
- data/vendor/assets/components/jquery/test/data/ua.txt +272 -0
- data/vendor/assets/components/jquery/test/data/with_fries.xml +25 -0
- data/vendor/assets/components/jquery/test/data/with_fries_over_jsonp.php +7 -0
- data/vendor/assets/components/jquery/test/delegatetest.html +228 -0
- data/vendor/assets/components/jquery/test/hovertest.html +158 -0
- data/vendor/assets/components/jquery/test/index.html +330 -0
- data/vendor/assets/components/jquery/test/localfile.html +75 -0
- data/vendor/assets/components/jquery/test/networkerror.html +84 -0
- data/vendor/assets/components/jquery/test/polluted.php +110 -0
- data/vendor/assets/components/jquery/test/readywait.html +70 -0
- data/vendor/assets/components/jquery/test/unit/ajax.js +1971 -0
- data/vendor/assets/components/jquery/test/unit/attributes.js +1332 -0
- data/vendor/assets/components/jquery/test/unit/callbacks.js +326 -0
- data/vendor/assets/components/jquery/test/unit/core.js +1332 -0
- data/vendor/assets/components/jquery/test/unit/css.js +1036 -0
- data/vendor/assets/components/jquery/test/unit/data.js +636 -0
- data/vendor/assets/components/jquery/test/unit/deferred.js +440 -0
- data/vendor/assets/components/jquery/test/unit/deprecated.js +1 -0
- data/vendor/assets/components/jquery/test/unit/dimensions.js +461 -0
- data/vendor/assets/components/jquery/test/unit/effects.js +2050 -0
- data/vendor/assets/components/jquery/test/unit/event.js +2690 -0
- data/vendor/assets/components/jquery/test/unit/exports.js +7 -0
- data/vendor/assets/components/jquery/test/unit/manipulation.js +2242 -0
- data/vendor/assets/components/jquery/test/unit/offset.js +549 -0
- data/vendor/assets/components/jquery/test/unit/queue.js +316 -0
- data/vendor/assets/components/jquery/test/unit/selector.js +185 -0
- data/vendor/assets/components/jquery/test/unit/serialize.js +146 -0
- data/vendor/assets/components/jquery/test/unit/support.js +384 -0
- data/vendor/assets/components/jquery/test/unit/traversing.js +667 -0
- data/vendor/assets/components/jquery/test/xhtml.php +5 -0
- data/vendor/assets/components/sir-trevor-js/CHANGELOG.md +44 -0
- data/vendor/assets/components/sir-trevor-js/Gemfile +3 -0
- data/vendor/assets/components/sir-trevor-js/Gemfile.lock +10 -0
- data/vendor/assets/components/sir-trevor-js/Gruntfile.js +109 -0
- data/vendor/assets/components/sir-trevor-js/MIT-LICENCE +20 -0
- data/vendor/assets/components/sir-trevor-js/Readme.md +84 -0
- data/vendor/assets/components/sir-trevor-js/bower.json +21 -0
- data/vendor/assets/components/sir-trevor-js/component.json +42 -0
- data/vendor/assets/components/sir-trevor-js/contributing.md +74 -0
- data/vendor/assets/components/sir-trevor-js/examples-component/component.json +14 -0
- data/vendor/assets/components/sir-trevor-js/examples-component/index.html +33 -0
- data/vendor/assets/components/sir-trevor-js/examples-component/index.js +29 -0
- data/vendor/assets/components/sir-trevor-js/examples-component/javascript/example_block.js +203 -0
- data/vendor/assets/components/sir-trevor-js/examples-component/javascript/limit_chars.js +46 -0
- data/vendor/assets/components/sir-trevor-js/examples-component/sir-trevor.gif +0 -0
- data/vendor/assets/components/sir-trevor-js/locales/cn.js +51 -0
- data/vendor/assets/components/sir-trevor-js/locales/de.js +51 -0
- data/vendor/assets/components/sir-trevor-js/locales/es.js +51 -0
- data/vendor/assets/components/sir-trevor-js/locales/fi.js +51 -0
- data/vendor/assets/components/sir-trevor-js/locales/fr.js +51 -0
- data/vendor/assets/components/sir-trevor-js/locales/pt.js +52 -0
- data/vendor/assets/components/sir-trevor-js/package.json +23 -0
- data/vendor/assets/components/sir-trevor-js/sir-trevor-icons.css +6 -0
- data/vendor/assets/components/sir-trevor-js/sir-trevor.css +393 -0
- data/vendor/assets/components/sir-trevor-js/sir-trevor.css.map +7 -0
- data/vendor/assets/components/sir-trevor-js/sir-trevor.js +5481 -0
- data/vendor/assets/components/sir-trevor-js/sir-trevor.min.js +13 -0
- data/vendor/assets/components/underscore/CNAME +1 -0
- data/vendor/assets/components/underscore/CONTRIBUTING.md +9 -0
- data/vendor/assets/components/underscore/LICENSE +22 -0
- data/vendor/assets/components/underscore/README.md +19 -0
- data/vendor/assets/components/underscore/Rakefile +10 -0
- data/vendor/assets/components/underscore/docs/docco.css +192 -0
- data/vendor/assets/components/underscore/docs/favicon.ico +0 -0
- data/vendor/assets/components/underscore/docs/images/background.png +0 -0
- data/vendor/assets/components/underscore/docs/images/underscore.png +0 -0
- data/vendor/assets/components/underscore/docs/underscore.html +823 -0
- data/vendor/assets/components/underscore/favicon.ico +0 -0
- data/vendor/assets/components/underscore/index.html +2467 -0
- data/vendor/assets/components/underscore/index.js +1 -0
- data/vendor/assets/components/underscore/package.json +16 -0
- data/vendor/assets/components/underscore/test/arrays.js +200 -0
- data/vendor/assets/components/underscore/test/chaining.js +59 -0
- data/vendor/assets/components/underscore/test/collections.js +453 -0
- data/vendor/assets/components/underscore/test/functions.js +265 -0
- data/vendor/assets/components/underscore/test/index.html +44 -0
- data/vendor/assets/components/underscore/test/objects.js +570 -0
- data/vendor/assets/components/underscore/test/speed.js +75 -0
- data/vendor/assets/components/underscore/test/utility.js +266 -0
- data/vendor/assets/components/underscore/test/vendor/jquery.js +9404 -0
- data/vendor/assets/components/underscore/test/vendor/jslitmus.js +670 -0
- data/vendor/assets/components/underscore/test/vendor/qunit.css +235 -0
- data/vendor/assets/components/underscore/test/vendor/qunit.js +1977 -0
- data/vendor/assets/components/underscore/test/vendor/runner.js +98 -0
- data/vendor/assets/components/underscore/underscore-min.js +1 -0
- data/vendor/assets/components/underscore/underscore.js +1226 -0
- metadata +473 -0
@@ -0,0 +1,265 @@
|
|
1
|
+
$(document).ready(function() {
|
2
|
+
|
3
|
+
module("Functions");
|
4
|
+
|
5
|
+
test("bind", function() {
|
6
|
+
var context = {name : 'moe'};
|
7
|
+
var func = function(arg) { return "name: " + (this.name || arg); };
|
8
|
+
var bound = _.bind(func, context);
|
9
|
+
equal(bound(), 'name: moe', 'can bind a function to a context');
|
10
|
+
|
11
|
+
bound = _(func).bind(context);
|
12
|
+
equal(bound(), 'name: moe', 'can do OO-style binding');
|
13
|
+
|
14
|
+
bound = _.bind(func, null, 'curly');
|
15
|
+
equal(bound(), 'name: curly', 'can bind without specifying a context');
|
16
|
+
|
17
|
+
func = function(salutation, name) { return salutation + ': ' + name; };
|
18
|
+
func = _.bind(func, this, 'hello');
|
19
|
+
equal(func('moe'), 'hello: moe', 'the function was partially applied in advance');
|
20
|
+
|
21
|
+
func = _.bind(func, this, 'curly');
|
22
|
+
equal(func(), 'hello: curly', 'the function was completely applied in advance');
|
23
|
+
|
24
|
+
func = function(salutation, firstname, lastname) { return salutation + ': ' + firstname + ' ' + lastname; };
|
25
|
+
func = _.bind(func, this, 'hello', 'moe', 'curly');
|
26
|
+
equal(func(), 'hello: moe curly', 'the function was partially applied in advance and can accept multiple arguments');
|
27
|
+
|
28
|
+
func = function(context, message) { equal(this, context, message); };
|
29
|
+
_.bind(func, 0, 0, 'can bind a function to `0`')();
|
30
|
+
_.bind(func, '', '', 'can bind a function to an empty string')();
|
31
|
+
_.bind(func, false, false, 'can bind a function to `false`')();
|
32
|
+
|
33
|
+
// These tests are only meaningful when using a browser without a native bind function
|
34
|
+
// To test this with a modern browser, set underscore's nativeBind to undefined
|
35
|
+
var F = function () { return this; };
|
36
|
+
var Boundf = _.bind(F, {hello: "moe curly"});
|
37
|
+
equal(Boundf().hello, "moe curly", "When called without the new operator, it's OK to be bound to the context");
|
38
|
+
});
|
39
|
+
|
40
|
+
test("partial", function() {
|
41
|
+
var obj = {name: 'moe'};
|
42
|
+
var func = function() { return this.name + ' ' + _.toArray(arguments).join(' '); };
|
43
|
+
|
44
|
+
obj.func = _.partial(func, 'a', 'b');
|
45
|
+
equal(obj.func('c', 'd'), 'moe a b c d', 'can partially apply');
|
46
|
+
});
|
47
|
+
|
48
|
+
test("bindAll", function() {
|
49
|
+
var curly = {name : 'curly'}, moe = {
|
50
|
+
name : 'moe',
|
51
|
+
getName : function() { return 'name: ' + this.name; },
|
52
|
+
sayHi : function() { return 'hi: ' + this.name; }
|
53
|
+
};
|
54
|
+
curly.getName = moe.getName;
|
55
|
+
_.bindAll(moe, 'getName', 'sayHi');
|
56
|
+
curly.sayHi = moe.sayHi;
|
57
|
+
equal(curly.getName(), 'name: curly', 'unbound function is bound to current object');
|
58
|
+
equal(curly.sayHi(), 'hi: moe', 'bound function is still bound to original object');
|
59
|
+
|
60
|
+
curly = {name : 'curly'};
|
61
|
+
moe = {
|
62
|
+
name : 'moe',
|
63
|
+
getName : function() { return 'name: ' + this.name; },
|
64
|
+
sayHi : function() { return 'hi: ' + this.name; }
|
65
|
+
};
|
66
|
+
_.bindAll(moe);
|
67
|
+
curly.sayHi = moe.sayHi;
|
68
|
+
equal(curly.sayHi(), 'hi: moe', 'calling bindAll with no arguments binds all functions to the object');
|
69
|
+
});
|
70
|
+
|
71
|
+
test("memoize", function() {
|
72
|
+
var fib = function(n) {
|
73
|
+
return n < 2 ? n : fib(n - 1) + fib(n - 2);
|
74
|
+
};
|
75
|
+
var fastFib = _.memoize(fib);
|
76
|
+
equal(fib(10), 55, 'a memoized version of fibonacci produces identical results');
|
77
|
+
equal(fastFib(10), 55, 'a memoized version of fibonacci produces identical results');
|
78
|
+
|
79
|
+
var o = function(str) {
|
80
|
+
return str;
|
81
|
+
};
|
82
|
+
var fastO = _.memoize(o);
|
83
|
+
equal(o('toString'), 'toString', 'checks hasOwnProperty');
|
84
|
+
equal(fastO('toString'), 'toString', 'checks hasOwnProperty');
|
85
|
+
});
|
86
|
+
|
87
|
+
asyncTest("delay", 2, function() {
|
88
|
+
var delayed = false;
|
89
|
+
_.delay(function(){ delayed = true; }, 100);
|
90
|
+
setTimeout(function(){ ok(!delayed, "didn't delay the function quite yet"); }, 50);
|
91
|
+
setTimeout(function(){ ok(delayed, 'delayed the function'); start(); }, 150);
|
92
|
+
});
|
93
|
+
|
94
|
+
asyncTest("defer", 1, function() {
|
95
|
+
var deferred = false;
|
96
|
+
_.defer(function(bool){ deferred = bool; }, true);
|
97
|
+
_.delay(function(){ ok(deferred, "deferred the function"); start(); }, 50);
|
98
|
+
});
|
99
|
+
|
100
|
+
asyncTest("throttle", 2, function() {
|
101
|
+
var counter = 0;
|
102
|
+
var incr = function(){ counter++; };
|
103
|
+
var throttledIncr = _.throttle(incr, 32);
|
104
|
+
throttledIncr(); throttledIncr();
|
105
|
+
|
106
|
+
equal(counter, 1, "incr was called immediately");
|
107
|
+
_.delay(function(){ equal(counter, 2, "incr was throttled"); start(); }, 64);
|
108
|
+
});
|
109
|
+
|
110
|
+
asyncTest("throttle arguments", 2, function() {
|
111
|
+
var value = 0;
|
112
|
+
var update = function(val){ value = val; };
|
113
|
+
var throttledUpdate = _.throttle(update, 32);
|
114
|
+
throttledUpdate(1); throttledUpdate(2);
|
115
|
+
_.delay(function(){ throttledUpdate(3); }, 64);
|
116
|
+
equal(value, 1, "updated to latest value");
|
117
|
+
_.delay(function(){ equal(value, 3, "updated to latest value"); start(); }, 96);
|
118
|
+
});
|
119
|
+
|
120
|
+
asyncTest("throttle once", 2, function() {
|
121
|
+
var counter = 0;
|
122
|
+
var incr = function(){ return ++counter; };
|
123
|
+
var throttledIncr = _.throttle(incr, 32);
|
124
|
+
var result = throttledIncr();
|
125
|
+
_.delay(function(){
|
126
|
+
equal(result, 1, "throttled functions return their value");
|
127
|
+
equal(counter, 1, "incr was called once"); start();
|
128
|
+
}, 64);
|
129
|
+
});
|
130
|
+
|
131
|
+
asyncTest("throttle twice", 1, function() {
|
132
|
+
var counter = 0;
|
133
|
+
var incr = function(){ counter++; };
|
134
|
+
var throttledIncr = _.throttle(incr, 32);
|
135
|
+
throttledIncr(); throttledIncr();
|
136
|
+
_.delay(function(){ equal(counter, 2, "incr was called twice"); start(); }, 64);
|
137
|
+
});
|
138
|
+
|
139
|
+
asyncTest("throttle repeatedly with results", 6, function() {
|
140
|
+
var counter = 0;
|
141
|
+
var incr = function(){ return ++counter; };
|
142
|
+
var throttledIncr = _.throttle(incr, 64);
|
143
|
+
var results = [];
|
144
|
+
var saveResult = function() { results.push(throttledIncr()); };
|
145
|
+
saveResult(); saveResult();
|
146
|
+
_.delay(saveResult, 32);
|
147
|
+
_.delay(saveResult, 80);
|
148
|
+
_.delay(saveResult, 96);
|
149
|
+
_.delay(saveResult, 144);
|
150
|
+
_.delay(function() {
|
151
|
+
equal(results[0], 1, "incr was called once");
|
152
|
+
equal(results[1], 1, "incr was throttled");
|
153
|
+
equal(results[2], 1, "incr was throttled");
|
154
|
+
equal(results[3], 2, "incr was called twice");
|
155
|
+
equal(results[4], 2, "incr was throttled");
|
156
|
+
equal(results[5], 3, "incr was called trailing");
|
157
|
+
start();
|
158
|
+
}, 192);
|
159
|
+
});
|
160
|
+
|
161
|
+
asyncTest("throttle triggers trailing call when invoked repeatedly", 2, function() {
|
162
|
+
var counter = 0;
|
163
|
+
var limit = 48;
|
164
|
+
var incr = function(){ counter++; };
|
165
|
+
var throttledIncr = _.throttle(incr, 32);
|
166
|
+
|
167
|
+
var stamp = new Date;
|
168
|
+
while ((new Date - stamp) < limit) {
|
169
|
+
throttledIncr();
|
170
|
+
}
|
171
|
+
var lastCount = counter;
|
172
|
+
ok(counter > 1);
|
173
|
+
|
174
|
+
_.delay(function() {
|
175
|
+
ok(counter > lastCount);
|
176
|
+
start();
|
177
|
+
}, 96);
|
178
|
+
});
|
179
|
+
|
180
|
+
asyncTest("debounce", 1, function() {
|
181
|
+
var counter = 0;
|
182
|
+
var incr = function(){ counter++; };
|
183
|
+
var debouncedIncr = _.debounce(incr, 32);
|
184
|
+
debouncedIncr(); debouncedIncr();
|
185
|
+
_.delay(debouncedIncr, 16);
|
186
|
+
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 96);
|
187
|
+
});
|
188
|
+
|
189
|
+
asyncTest("debounce asap", 4, function() {
|
190
|
+
var a, b;
|
191
|
+
var counter = 0;
|
192
|
+
var incr = function(){ return ++counter; };
|
193
|
+
var debouncedIncr = _.debounce(incr, 64, true);
|
194
|
+
a = debouncedIncr();
|
195
|
+
b = debouncedIncr();
|
196
|
+
equal(a, 1);
|
197
|
+
equal(b, 1);
|
198
|
+
equal(counter, 1, 'incr was called immediately');
|
199
|
+
_.delay(debouncedIncr, 16);
|
200
|
+
_.delay(debouncedIncr, 32);
|
201
|
+
_.delay(debouncedIncr, 48);
|
202
|
+
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 128);
|
203
|
+
});
|
204
|
+
|
205
|
+
asyncTest("debounce asap recursively", 2, function() {
|
206
|
+
var counter = 0;
|
207
|
+
var debouncedIncr = _.debounce(function(){
|
208
|
+
counter++;
|
209
|
+
if (counter < 10) debouncedIncr();
|
210
|
+
}, 32, true);
|
211
|
+
debouncedIncr();
|
212
|
+
equal(counter, 1, "incr was called immediately");
|
213
|
+
_.delay(function(){ equal(counter, 1, "incr was debounced"); start(); }, 96);
|
214
|
+
});
|
215
|
+
|
216
|
+
test("once", function() {
|
217
|
+
var num = 0;
|
218
|
+
var increment = _.once(function(){ num++; });
|
219
|
+
increment();
|
220
|
+
increment();
|
221
|
+
equal(num, 1);
|
222
|
+
});
|
223
|
+
|
224
|
+
test("wrap", function() {
|
225
|
+
var greet = function(name){ return "hi: " + name; };
|
226
|
+
var backwards = _.wrap(greet, function(func, name){ return func(name) + ' ' + name.split('').reverse().join(''); });
|
227
|
+
equal(backwards('moe'), 'hi: moe eom', 'wrapped the saluation function');
|
228
|
+
|
229
|
+
var inner = function(){ return "Hello "; };
|
230
|
+
var obj = {name : "Moe"};
|
231
|
+
obj.hi = _.wrap(inner, function(fn){ return fn() + this.name; });
|
232
|
+
equal(obj.hi(), "Hello Moe");
|
233
|
+
|
234
|
+
var noop = function(){};
|
235
|
+
var wrapped = _.wrap(noop, function(fn){ return Array.prototype.slice.call(arguments, 0); });
|
236
|
+
var ret = wrapped(['whats', 'your'], 'vector', 'victor');
|
237
|
+
deepEqual(ret, [noop, ['whats', 'your'], 'vector', 'victor']);
|
238
|
+
});
|
239
|
+
|
240
|
+
test("compose", function() {
|
241
|
+
var greet = function(name){ return "hi: " + name; };
|
242
|
+
var exclaim = function(sentence){ return sentence + '!'; };
|
243
|
+
var composed = _.compose(exclaim, greet);
|
244
|
+
equal(composed('moe'), 'hi: moe!', 'can compose a function that takes another');
|
245
|
+
|
246
|
+
composed = _.compose(greet, exclaim);
|
247
|
+
equal(composed('moe'), 'hi: moe!', 'in this case, the functions are also commutative');
|
248
|
+
});
|
249
|
+
|
250
|
+
test("after", function() {
|
251
|
+
var testAfter = function(afterAmount, timesCalled) {
|
252
|
+
var afterCalled = 0;
|
253
|
+
var after = _.after(afterAmount, function() {
|
254
|
+
afterCalled++;
|
255
|
+
});
|
256
|
+
while (timesCalled--) after();
|
257
|
+
return afterCalled;
|
258
|
+
};
|
259
|
+
|
260
|
+
equal(testAfter(5, 5), 1, "after(N) should fire after being called N times");
|
261
|
+
equal(testAfter(5, 4), 0, "after(N) should not fire unless called N times");
|
262
|
+
equal(testAfter(0, 0), 1, "after(0) should fire immediately");
|
263
|
+
});
|
264
|
+
|
265
|
+
});
|
@@ -0,0 +1,44 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Underscore Test Suite</title>
|
5
|
+
<link rel="stylesheet" href="vendor/qunit.css" type="text/css" media="screen">
|
6
|
+
<script src="vendor/jquery.js"></script>
|
7
|
+
<script src="vendor/qunit.js"></script>
|
8
|
+
<script src="vendor/jslitmus.js"></script>
|
9
|
+
<script src="../underscore.js"></script>
|
10
|
+
|
11
|
+
<script src="collections.js"></script>
|
12
|
+
<script src="arrays.js"></script>
|
13
|
+
<script src="functions.js"></script>
|
14
|
+
<script src="objects.js"></script>
|
15
|
+
<script src="utility.js"></script>
|
16
|
+
<script src="chaining.js"></script>
|
17
|
+
<script src="speed.js"></script>
|
18
|
+
</head>
|
19
|
+
<body>
|
20
|
+
<div id="qunit"></div>
|
21
|
+
<div id="qunit-fixture">
|
22
|
+
<div id="map-test">
|
23
|
+
<div id="id1"></div>
|
24
|
+
<div id="id2"></div>
|
25
|
+
</div>
|
26
|
+
</div>
|
27
|
+
<br>
|
28
|
+
<h1 class="qunit-header">Underscore Speed Suite</h1>
|
29
|
+
<p>
|
30
|
+
A representative sample of the functions are benchmarked here, to provide
|
31
|
+
a sense of how fast they might run in different browsers.
|
32
|
+
Each iteration runs on an array of 1000 elements.<br /><br />
|
33
|
+
For example, the 'intersection' test measures the number of times you can
|
34
|
+
find the intersection of two thousand-element arrays in one second.
|
35
|
+
</p>
|
36
|
+
<br>
|
37
|
+
<script type="text/html" id="template">
|
38
|
+
<%
|
39
|
+
// a comment
|
40
|
+
if (data) { data += 12345; }; %>
|
41
|
+
<li><%= data %></li>
|
42
|
+
</script>
|
43
|
+
</body>
|
44
|
+
</html>
|
@@ -0,0 +1,570 @@
|
|
1
|
+
$(document).ready(function() {
|
2
|
+
|
3
|
+
module("Objects");
|
4
|
+
|
5
|
+
test("keys", function() {
|
6
|
+
equal(_.keys({one : 1, two : 2}).join(', '), 'one, two', 'can extract the keys from an object');
|
7
|
+
// the test above is not safe because it relies on for-in enumeration order
|
8
|
+
var a = []; a[1] = 0;
|
9
|
+
equal(_.keys(a).join(', '), '1', 'is not fooled by sparse arrays; see issue #95');
|
10
|
+
raises(function() { _.keys(null); }, TypeError, 'throws an error for `null` values');
|
11
|
+
raises(function() { _.keys(void 0); }, TypeError, 'throws an error for `undefined` values');
|
12
|
+
raises(function() { _.keys(1); }, TypeError, 'throws an error for number primitives');
|
13
|
+
raises(function() { _.keys('a'); }, TypeError, 'throws an error for string primitives');
|
14
|
+
raises(function() { _.keys(true); }, TypeError, 'throws an error for boolean primitives');
|
15
|
+
});
|
16
|
+
|
17
|
+
test("values", function() {
|
18
|
+
equal(_.values({one: 1, two: 2}).join(', '), '1, 2', 'can extract the values from an object');
|
19
|
+
equal(_.values({one: 1, two: 2, length: 3}).join(', '), '1, 2, 3', '... even when one of them is "length"');
|
20
|
+
});
|
21
|
+
|
22
|
+
test("pairs", function() {
|
23
|
+
deepEqual(_.pairs({one: 1, two: 2}), [['one', 1], ['two', 2]], 'can convert an object into pairs');
|
24
|
+
deepEqual(_.pairs({one: 1, two: 2, length: 3}), [['one', 1], ['two', 2], ['length', 3]], '... even when one of them is "length"');
|
25
|
+
});
|
26
|
+
|
27
|
+
test("invert", function() {
|
28
|
+
var obj = {first: 'Moe', second: 'Larry', third: 'Curly'};
|
29
|
+
equal(_.keys(_.invert(obj)).join(' '), 'Moe Larry Curly', 'can invert an object');
|
30
|
+
ok(_.isEqual(_.invert(_.invert(obj)), obj), 'two inverts gets you back where you started');
|
31
|
+
|
32
|
+
var obj = {length: 3};
|
33
|
+
ok(_.invert(obj)['3'] == 'length', 'can invert an object with "length"')
|
34
|
+
});
|
35
|
+
|
36
|
+
test("functions", function() {
|
37
|
+
var obj = {a : 'dash', b : _.map, c : (/yo/), d : _.reduce};
|
38
|
+
ok(_.isEqual(['b', 'd'], _.functions(obj)), 'can grab the function names of any passed-in object');
|
39
|
+
|
40
|
+
var Animal = function(){};
|
41
|
+
Animal.prototype.run = function(){};
|
42
|
+
equal(_.functions(new Animal).join(''), 'run', 'also looks up functions on the prototype');
|
43
|
+
});
|
44
|
+
|
45
|
+
test("extend", function() {
|
46
|
+
var result;
|
47
|
+
equal(_.extend({}, {a:'b'}).a, 'b', 'can extend an object with the attributes of another');
|
48
|
+
equal(_.extend({a:'x'}, {a:'b'}).a, 'b', 'properties in source override destination');
|
49
|
+
equal(_.extend({x:'x'}, {a:'b'}).x, 'x', 'properties not in source dont get overriden');
|
50
|
+
result = _.extend({x:'x'}, {a:'a'}, {b:'b'});
|
51
|
+
ok(_.isEqual(result, {x:'x', a:'a', b:'b'}), 'can extend from multiple source objects');
|
52
|
+
result = _.extend({x:'x'}, {a:'a', x:2}, {a:'b'});
|
53
|
+
ok(_.isEqual(result, {x:2, a:'b'}), 'extending from multiple source objects last property trumps');
|
54
|
+
result = _.extend({}, {a: void 0, b: null});
|
55
|
+
equal(_.keys(result).join(''), 'ab', 'extend does not copy undefined values');
|
56
|
+
|
57
|
+
try {
|
58
|
+
result = {};
|
59
|
+
_.extend(result, null, undefined, {a:1});
|
60
|
+
} catch(ex) {}
|
61
|
+
|
62
|
+
equal(result.a, 1, 'should not error on `null` or `undefined` sources');
|
63
|
+
});
|
64
|
+
|
65
|
+
test("pick", function() {
|
66
|
+
var result;
|
67
|
+
result = _.pick({a:1, b:2, c:3}, 'a', 'c');
|
68
|
+
ok(_.isEqual(result, {a:1, c:3}), 'can restrict properties to those named');
|
69
|
+
result = _.pick({a:1, b:2, c:3}, ['b', 'c']);
|
70
|
+
ok(_.isEqual(result, {b:2, c:3}), 'can restrict properties to those named in an array');
|
71
|
+
result = _.pick({a:1, b:2, c:3}, ['a'], 'b');
|
72
|
+
ok(_.isEqual(result, {a:1, b:2}), 'can restrict properties to those named in mixed args');
|
73
|
+
|
74
|
+
var Obj = function(){};
|
75
|
+
Obj.prototype = {a: 1, b: 2, c: 3};
|
76
|
+
ok(_.isEqual(_.pick(new Obj, 'a', 'c'), {a:1, c: 3}), 'include prototype props');
|
77
|
+
});
|
78
|
+
|
79
|
+
test("omit", function() {
|
80
|
+
var result;
|
81
|
+
result = _.omit({a:1, b:2, c:3}, 'b');
|
82
|
+
ok(_.isEqual(result, {a:1, c:3}), 'can omit a single named property');
|
83
|
+
result = _.omit({a:1, b:2, c:3}, 'a', 'c');
|
84
|
+
ok(_.isEqual(result, {b:2}), 'can omit several named properties');
|
85
|
+
result = _.omit({a:1, b:2, c:3}, ['b', 'c']);
|
86
|
+
ok(_.isEqual(result, {a:1}), 'can omit properties named in an array');
|
87
|
+
|
88
|
+
var Obj = function(){};
|
89
|
+
Obj.prototype = {a: 1, b: 2, c: 3};
|
90
|
+
ok(_.isEqual(_.omit(new Obj, 'b'), {a:1, c: 3}), 'include prototype props');
|
91
|
+
});
|
92
|
+
|
93
|
+
test("defaults", function() {
|
94
|
+
var result;
|
95
|
+
var options = {zero: 0, one: 1, empty: "", nan: NaN, string: "string"};
|
96
|
+
|
97
|
+
_.defaults(options, {zero: 1, one: 10, twenty: 20});
|
98
|
+
equal(options.zero, 0, 'value exists');
|
99
|
+
equal(options.one, 1, 'value exists');
|
100
|
+
equal(options.twenty, 20, 'default applied');
|
101
|
+
|
102
|
+
_.defaults(options, {empty: "full"}, {nan: "nan"}, {word: "word"}, {word: "dog"});
|
103
|
+
equal(options.empty, "", 'value exists');
|
104
|
+
ok(_.isNaN(options.nan), "NaN isn't overridden");
|
105
|
+
equal(options.word, "word", 'new value is added, first one wins');
|
106
|
+
|
107
|
+
try {
|
108
|
+
options = {};
|
109
|
+
_.defaults(options, null, undefined, {a:1});
|
110
|
+
} catch(ex) {}
|
111
|
+
|
112
|
+
equal(options.a, 1, 'should not error on `null` or `undefined` sources');
|
113
|
+
});
|
114
|
+
|
115
|
+
test("clone", function() {
|
116
|
+
var moe = {name : 'moe', lucky : [13, 27, 34]};
|
117
|
+
var clone = _.clone(moe);
|
118
|
+
equal(clone.name, 'moe', 'the clone as the attributes of the original');
|
119
|
+
|
120
|
+
clone.name = 'curly';
|
121
|
+
ok(clone.name == 'curly' && moe.name == 'moe', 'clones can change shallow attributes without affecting the original');
|
122
|
+
|
123
|
+
clone.lucky.push(101);
|
124
|
+
equal(_.last(moe.lucky), 101, 'changes to deep attributes are shared with the original');
|
125
|
+
|
126
|
+
equal(_.clone(undefined), void 0, 'non objects should not be changed by clone');
|
127
|
+
equal(_.clone(1), 1, 'non objects should not be changed by clone');
|
128
|
+
equal(_.clone(null), null, 'non objects should not be changed by clone');
|
129
|
+
});
|
130
|
+
|
131
|
+
test("isEqual", function() {
|
132
|
+
function First() {
|
133
|
+
this.value = 1;
|
134
|
+
}
|
135
|
+
First.prototype.value = 1;
|
136
|
+
function Second() {
|
137
|
+
this.value = 1;
|
138
|
+
}
|
139
|
+
Second.prototype.value = 2;
|
140
|
+
|
141
|
+
// Basic equality and identity comparisons.
|
142
|
+
ok(_.isEqual(null, null), "`null` is equal to `null`");
|
143
|
+
ok(_.isEqual(), "`undefined` is equal to `undefined`");
|
144
|
+
|
145
|
+
ok(!_.isEqual(0, -0), "`0` is not equal to `-0`");
|
146
|
+
ok(!_.isEqual(-0, 0), "Commutative equality is implemented for `0` and `-0`");
|
147
|
+
ok(!_.isEqual(null, undefined), "`null` is not equal to `undefined`");
|
148
|
+
ok(!_.isEqual(undefined, null), "Commutative equality is implemented for `null` and `undefined`");
|
149
|
+
|
150
|
+
// String object and primitive comparisons.
|
151
|
+
ok(_.isEqual("Curly", "Curly"), "Identical string primitives are equal");
|
152
|
+
ok(_.isEqual(new String("Curly"), new String("Curly")), "String objects with identical primitive values are equal");
|
153
|
+
ok(_.isEqual(new String("Curly"), "Curly"), "String primitives and their corresponding object wrappers are equal");
|
154
|
+
ok(_.isEqual("Curly", new String("Curly")), "Commutative equality is implemented for string objects and primitives");
|
155
|
+
|
156
|
+
ok(!_.isEqual("Curly", "Larry"), "String primitives with different values are not equal");
|
157
|
+
ok(!_.isEqual(new String("Curly"), new String("Larry")), "String objects with different primitive values are not equal");
|
158
|
+
ok(!_.isEqual(new String("Curly"), {toString: function(){ return "Curly"; }}), "String objects and objects with a custom `toString` method are not equal");
|
159
|
+
|
160
|
+
// Number object and primitive comparisons.
|
161
|
+
ok(_.isEqual(75, 75), "Identical number primitives are equal");
|
162
|
+
ok(_.isEqual(new Number(75), new Number(75)), "Number objects with identical primitive values are equal");
|
163
|
+
ok(_.isEqual(75, new Number(75)), "Number primitives and their corresponding object wrappers are equal");
|
164
|
+
ok(_.isEqual(new Number(75), 75), "Commutative equality is implemented for number objects and primitives");
|
165
|
+
ok(!_.isEqual(new Number(0), -0), "`new Number(0)` and `-0` are not equal");
|
166
|
+
ok(!_.isEqual(0, new Number(-0)), "Commutative equality is implemented for `new Number(0)` and `-0`");
|
167
|
+
|
168
|
+
ok(!_.isEqual(new Number(75), new Number(63)), "Number objects with different primitive values are not equal");
|
169
|
+
ok(!_.isEqual(new Number(63), {valueOf: function(){ return 63; }}), "Number objects and objects with a `valueOf` method are not equal");
|
170
|
+
|
171
|
+
// Comparisons involving `NaN`.
|
172
|
+
ok(_.isEqual(NaN, NaN), "`NaN` is equal to `NaN`");
|
173
|
+
ok(!_.isEqual(61, NaN), "A number primitive is not equal to `NaN`");
|
174
|
+
ok(!_.isEqual(new Number(79), NaN), "A number object is not equal to `NaN`");
|
175
|
+
ok(!_.isEqual(Infinity, NaN), "`Infinity` is not equal to `NaN`");
|
176
|
+
|
177
|
+
// Boolean object and primitive comparisons.
|
178
|
+
ok(_.isEqual(true, true), "Identical boolean primitives are equal");
|
179
|
+
ok(_.isEqual(new Boolean, new Boolean), "Boolean objects with identical primitive values are equal");
|
180
|
+
ok(_.isEqual(true, new Boolean(true)), "Boolean primitives and their corresponding object wrappers are equal");
|
181
|
+
ok(_.isEqual(new Boolean(true), true), "Commutative equality is implemented for booleans");
|
182
|
+
ok(!_.isEqual(new Boolean(true), new Boolean), "Boolean objects with different primitive values are not equal");
|
183
|
+
|
184
|
+
// Common type coercions.
|
185
|
+
ok(!_.isEqual(true, new Boolean(false)), "Boolean objects are not equal to the boolean primitive `true`");
|
186
|
+
ok(!_.isEqual("75", 75), "String and number primitives with like values are not equal");
|
187
|
+
ok(!_.isEqual(new Number(63), new String(63)), "String and number objects with like values are not equal");
|
188
|
+
ok(!_.isEqual(75, "75"), "Commutative equality is implemented for like string and number values");
|
189
|
+
ok(!_.isEqual(0, ""), "Number and string primitives with like values are not equal");
|
190
|
+
ok(!_.isEqual(1, true), "Number and boolean primitives with like values are not equal");
|
191
|
+
ok(!_.isEqual(new Boolean(false), new Number(0)), "Boolean and number objects with like values are not equal");
|
192
|
+
ok(!_.isEqual(false, new String("")), "Boolean primitives and string objects with like values are not equal");
|
193
|
+
ok(!_.isEqual(12564504e5, new Date(2009, 9, 25)), "Dates and their corresponding numeric primitive values are not equal");
|
194
|
+
|
195
|
+
// Dates.
|
196
|
+
ok(_.isEqual(new Date(2009, 9, 25), new Date(2009, 9, 25)), "Date objects referencing identical times are equal");
|
197
|
+
ok(!_.isEqual(new Date(2009, 9, 25), new Date(2009, 11, 13)), "Date objects referencing different times are not equal");
|
198
|
+
ok(!_.isEqual(new Date(2009, 11, 13), {
|
199
|
+
getTime: function(){
|
200
|
+
return 12606876e5;
|
201
|
+
}
|
202
|
+
}), "Date objects and objects with a `getTime` method are not equal");
|
203
|
+
ok(!_.isEqual(new Date("Curly"), new Date("Curly")), "Invalid dates are not equal");
|
204
|
+
|
205
|
+
// Functions.
|
206
|
+
ok(!_.isEqual(First, Second), "Different functions with identical bodies and source code representations are not equal");
|
207
|
+
|
208
|
+
// RegExps.
|
209
|
+
ok(_.isEqual(/(?:)/gim, /(?:)/gim), "RegExps with equivalent patterns and flags are equal");
|
210
|
+
ok(!_.isEqual(/(?:)/g, /(?:)/gi), "RegExps with equivalent patterns and different flags are not equal");
|
211
|
+
ok(!_.isEqual(/Moe/gim, /Curly/gim), "RegExps with different patterns and equivalent flags are not equal");
|
212
|
+
ok(!_.isEqual(/(?:)/gi, /(?:)/g), "Commutative equality is implemented for RegExps");
|
213
|
+
ok(!_.isEqual(/Curly/g, {source: "Larry", global: true, ignoreCase: false, multiline: false}), "RegExps and RegExp-like objects are not equal");
|
214
|
+
|
215
|
+
// Empty arrays, array-like objects, and object literals.
|
216
|
+
ok(_.isEqual({}, {}), "Empty object literals are equal");
|
217
|
+
ok(_.isEqual([], []), "Empty array literals are equal");
|
218
|
+
ok(_.isEqual([{}], [{}]), "Empty nested arrays and objects are equal");
|
219
|
+
ok(!_.isEqual({length: 0}, []), "Array-like objects and arrays are not equal.");
|
220
|
+
ok(!_.isEqual([], {length: 0}), "Commutative equality is implemented for array-like objects");
|
221
|
+
|
222
|
+
ok(!_.isEqual({}, []), "Object literals and array literals are not equal");
|
223
|
+
ok(!_.isEqual([], {}), "Commutative equality is implemented for objects and arrays");
|
224
|
+
|
225
|
+
// Arrays with primitive and object values.
|
226
|
+
ok(_.isEqual([1, "Larry", true], [1, "Larry", true]), "Arrays containing identical primitives are equal");
|
227
|
+
ok(_.isEqual([(/Moe/g), new Date(2009, 9, 25)], [(/Moe/g), new Date(2009, 9, 25)]), "Arrays containing equivalent elements are equal");
|
228
|
+
|
229
|
+
// Multi-dimensional arrays.
|
230
|
+
var a = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}];
|
231
|
+
var b = [new Number(47), false, "Larry", /Moe/, new Date(2009, 11, 13), ['running', 'biking', new String('programming')], {a: 47}];
|
232
|
+
ok(_.isEqual(a, b), "Arrays containing nested arrays and objects are recursively compared");
|
233
|
+
|
234
|
+
// Overwrite the methods defined in ES 5.1 section 15.4.4.
|
235
|
+
a.forEach = a.map = a.filter = a.every = a.indexOf = a.lastIndexOf = a.some = a.reduce = a.reduceRight = null;
|
236
|
+
b.join = b.pop = b.reverse = b.shift = b.slice = b.splice = b.concat = b.sort = b.unshift = null;
|
237
|
+
|
238
|
+
// Array elements and properties.
|
239
|
+
ok(_.isEqual(a, b), "Arrays containing equivalent elements and different non-numeric properties are equal");
|
240
|
+
a.push("White Rocks");
|
241
|
+
ok(!_.isEqual(a, b), "Arrays of different lengths are not equal");
|
242
|
+
a.push("East Boulder");
|
243
|
+
b.push("Gunbarrel Ranch", "Teller Farm");
|
244
|
+
ok(!_.isEqual(a, b), "Arrays of identical lengths containing different elements are not equal");
|
245
|
+
|
246
|
+
// Sparse arrays.
|
247
|
+
ok(_.isEqual(Array(3), Array(3)), "Sparse arrays of identical lengths are equal");
|
248
|
+
ok(!_.isEqual(Array(3), Array(6)), "Sparse arrays of different lengths are not equal when both are empty");
|
249
|
+
|
250
|
+
// Simple objects.
|
251
|
+
ok(_.isEqual({a: "Curly", b: 1, c: true}, {a: "Curly", b: 1, c: true}), "Objects containing identical primitives are equal");
|
252
|
+
ok(_.isEqual({a: /Curly/g, b: new Date(2009, 11, 13)}, {a: /Curly/g, b: new Date(2009, 11, 13)}), "Objects containing equivalent members are equal");
|
253
|
+
ok(!_.isEqual({a: 63, b: 75}, {a: 61, b: 55}), "Objects of identical sizes with different values are not equal");
|
254
|
+
ok(!_.isEqual({a: 63, b: 75}, {a: 61, c: 55}), "Objects of identical sizes with different property names are not equal");
|
255
|
+
ok(!_.isEqual({a: 1, b: 2}, {a: 1}), "Objects of different sizes are not equal");
|
256
|
+
ok(!_.isEqual({a: 1}, {a: 1, b: 2}), "Commutative equality is implemented for objects");
|
257
|
+
ok(!_.isEqual({x: 1, y: undefined}, {x: 1, z: 2}), "Objects with identical keys and different values are not equivalent");
|
258
|
+
|
259
|
+
// `A` contains nested objects and arrays.
|
260
|
+
a = {
|
261
|
+
name: new String("Moe Howard"),
|
262
|
+
age: new Number(77),
|
263
|
+
stooge: true,
|
264
|
+
hobbies: ["acting"],
|
265
|
+
film: {
|
266
|
+
name: "Sing a Song of Six Pants",
|
267
|
+
release: new Date(1947, 9, 30),
|
268
|
+
stars: [new String("Larry Fine"), "Shemp Howard"],
|
269
|
+
minutes: new Number(16),
|
270
|
+
seconds: 54
|
271
|
+
}
|
272
|
+
};
|
273
|
+
|
274
|
+
// `B` contains equivalent nested objects and arrays.
|
275
|
+
b = {
|
276
|
+
name: new String("Moe Howard"),
|
277
|
+
age: new Number(77),
|
278
|
+
stooge: true,
|
279
|
+
hobbies: ["acting"],
|
280
|
+
film: {
|
281
|
+
name: "Sing a Song of Six Pants",
|
282
|
+
release: new Date(1947, 9, 30),
|
283
|
+
stars: [new String("Larry Fine"), "Shemp Howard"],
|
284
|
+
minutes: new Number(16),
|
285
|
+
seconds: 54
|
286
|
+
}
|
287
|
+
};
|
288
|
+
ok(_.isEqual(a, b), "Objects with nested equivalent members are recursively compared");
|
289
|
+
|
290
|
+
// Instances.
|
291
|
+
ok(_.isEqual(new First, new First), "Object instances are equal");
|
292
|
+
ok(!_.isEqual(new First, new Second), "Objects with different constructors and identical own properties are not equal");
|
293
|
+
ok(!_.isEqual({value: 1}, new First), "Object instances and objects sharing equivalent properties are not equal");
|
294
|
+
ok(!_.isEqual({value: 2}, new Second), "The prototype chain of objects should not be examined");
|
295
|
+
|
296
|
+
// Circular Arrays.
|
297
|
+
(a = []).push(a);
|
298
|
+
(b = []).push(b);
|
299
|
+
ok(_.isEqual(a, b), "Arrays containing circular references are equal");
|
300
|
+
a.push(new String("Larry"));
|
301
|
+
b.push(new String("Larry"));
|
302
|
+
ok(_.isEqual(a, b), "Arrays containing circular references and equivalent properties are equal");
|
303
|
+
a.push("Shemp");
|
304
|
+
b.push("Curly");
|
305
|
+
ok(!_.isEqual(a, b), "Arrays containing circular references and different properties are not equal");
|
306
|
+
|
307
|
+
// More circular arrays #767.
|
308
|
+
a = ["everything is checked but", "this", "is not"];
|
309
|
+
a[1] = a;
|
310
|
+
b = ["everything is checked but", ["this", "array"], "is not"];
|
311
|
+
ok(!_.isEqual(a, b), "Comparison of circular references with non-circular references are not equal");
|
312
|
+
|
313
|
+
// Circular Objects.
|
314
|
+
a = {abc: null};
|
315
|
+
b = {abc: null};
|
316
|
+
a.abc = a;
|
317
|
+
b.abc = b;
|
318
|
+
ok(_.isEqual(a, b), "Objects containing circular references are equal");
|
319
|
+
a.def = 75;
|
320
|
+
b.def = 75;
|
321
|
+
ok(_.isEqual(a, b), "Objects containing circular references and equivalent properties are equal");
|
322
|
+
a.def = new Number(75);
|
323
|
+
b.def = new Number(63);
|
324
|
+
ok(!_.isEqual(a, b), "Objects containing circular references and different properties are not equal");
|
325
|
+
|
326
|
+
// More circular objects #767.
|
327
|
+
a = {everything: "is checked", but: "this", is: "not"};
|
328
|
+
a.but = a;
|
329
|
+
b = {everything: "is checked", but: {that:"object"}, is: "not"};
|
330
|
+
ok(!_.isEqual(a, b), "Comparison of circular references with non-circular object references are not equal");
|
331
|
+
|
332
|
+
// Cyclic Structures.
|
333
|
+
a = [{abc: null}];
|
334
|
+
b = [{abc: null}];
|
335
|
+
(a[0].abc = a).push(a);
|
336
|
+
(b[0].abc = b).push(b);
|
337
|
+
ok(_.isEqual(a, b), "Cyclic structures are equal");
|
338
|
+
a[0].def = "Larry";
|
339
|
+
b[0].def = "Larry";
|
340
|
+
ok(_.isEqual(a, b), "Cyclic structures containing equivalent properties are equal");
|
341
|
+
a[0].def = new String("Larry");
|
342
|
+
b[0].def = new String("Curly");
|
343
|
+
ok(!_.isEqual(a, b), "Cyclic structures containing different properties are not equal");
|
344
|
+
|
345
|
+
// Complex Circular References.
|
346
|
+
a = {foo: {b: {foo: {c: {foo: null}}}}};
|
347
|
+
b = {foo: {b: {foo: {c: {foo: null}}}}};
|
348
|
+
a.foo.b.foo.c.foo = a;
|
349
|
+
b.foo.b.foo.c.foo = b;
|
350
|
+
ok(_.isEqual(a, b), "Cyclic structures with nested and identically-named properties are equal");
|
351
|
+
|
352
|
+
// Chaining.
|
353
|
+
ok(!_.isEqual(_({x: 1, y: undefined}).chain(), _({x: 1, z: 2}).chain()), 'Chained objects containing different values are not equal');
|
354
|
+
|
355
|
+
a = _({x: 1, y: 2}).chain();
|
356
|
+
b = _({x: 1, y: 2}).chain();
|
357
|
+
equal(_.isEqual(a.isEqual(b), _(true)), true, '`isEqual` can be chained');
|
358
|
+
|
359
|
+
// Objects from another frame.
|
360
|
+
ok(_.isEqual({}, iObject));
|
361
|
+
});
|
362
|
+
|
363
|
+
test("isEmpty", function() {
|
364
|
+
ok(!_([1]).isEmpty(), '[1] is not empty');
|
365
|
+
ok(_.isEmpty([]), '[] is empty');
|
366
|
+
ok(!_.isEmpty({one : 1}), '{one : 1} is not empty');
|
367
|
+
ok(_.isEmpty({}), '{} is empty');
|
368
|
+
ok(_.isEmpty(new RegExp('')), 'objects with prototype properties are empty');
|
369
|
+
ok(_.isEmpty(null), 'null is empty');
|
370
|
+
ok(_.isEmpty(), 'undefined is empty');
|
371
|
+
ok(_.isEmpty(''), 'the empty string is empty');
|
372
|
+
ok(!_.isEmpty('moe'), 'but other strings are not');
|
373
|
+
|
374
|
+
var obj = {one : 1};
|
375
|
+
delete obj.one;
|
376
|
+
ok(_.isEmpty(obj), 'deleting all the keys from an object empties it');
|
377
|
+
});
|
378
|
+
|
379
|
+
// Setup remote variables for iFrame tests.
|
380
|
+
var iframe = document.createElement('iframe');
|
381
|
+
jQuery(iframe).appendTo(document.body);
|
382
|
+
var iDoc = iframe.contentDocument || iframe.contentWindow.document;
|
383
|
+
iDoc.write(
|
384
|
+
"<script>\
|
385
|
+
parent.iElement = document.createElement('div');\
|
386
|
+
parent.iArguments = (function(){ return arguments; })(1, 2, 3);\
|
387
|
+
parent.iArray = [1, 2, 3];\
|
388
|
+
parent.iString = new String('hello');\
|
389
|
+
parent.iNumber = new Number(100);\
|
390
|
+
parent.iFunction = (function(){});\
|
391
|
+
parent.iDate = new Date();\
|
392
|
+
parent.iRegExp = /hi/;\
|
393
|
+
parent.iNaN = NaN;\
|
394
|
+
parent.iNull = null;\
|
395
|
+
parent.iBoolean = new Boolean(false);\
|
396
|
+
parent.iUndefined = undefined;\
|
397
|
+
parent.iObject = {};\
|
398
|
+
</script>"
|
399
|
+
);
|
400
|
+
iDoc.close();
|
401
|
+
|
402
|
+
test("isElement", function() {
|
403
|
+
ok(!_.isElement('div'), 'strings are not dom elements');
|
404
|
+
ok(_.isElement($('html')[0]), 'the html tag is a DOM element');
|
405
|
+
ok(_.isElement(iElement), 'even from another frame');
|
406
|
+
});
|
407
|
+
|
408
|
+
test("isArguments", function() {
|
409
|
+
var args = (function(){ return arguments; })(1, 2, 3);
|
410
|
+
ok(!_.isArguments('string'), 'a string is not an arguments object');
|
411
|
+
ok(!_.isArguments(_.isArguments), 'a function is not an arguments object');
|
412
|
+
ok(_.isArguments(args), 'but the arguments object is an arguments object');
|
413
|
+
ok(!_.isArguments(_.toArray(args)), 'but not when it\'s converted into an array');
|
414
|
+
ok(!_.isArguments([1,2,3]), 'and not vanilla arrays.');
|
415
|
+
ok(_.isArguments(iArguments), 'even from another frame');
|
416
|
+
});
|
417
|
+
|
418
|
+
test("isObject", function() {
|
419
|
+
ok(_.isObject(arguments), 'the arguments object is object');
|
420
|
+
ok(_.isObject([1, 2, 3]), 'and arrays');
|
421
|
+
ok(_.isObject($('html')[0]), 'and DOM element');
|
422
|
+
ok(_.isObject(iElement), 'even from another frame');
|
423
|
+
ok(_.isObject(function () {}), 'and functions');
|
424
|
+
ok(_.isObject(iFunction), 'even from another frame');
|
425
|
+
ok(!_.isObject(null), 'but not null');
|
426
|
+
ok(!_.isObject(undefined), 'and not undefined');
|
427
|
+
ok(!_.isObject('string'), 'and not string');
|
428
|
+
ok(!_.isObject(12), 'and not number');
|
429
|
+
ok(!_.isObject(true), 'and not boolean');
|
430
|
+
ok(_.isObject(new String('string')), 'but new String()');
|
431
|
+
});
|
432
|
+
|
433
|
+
test("isArray", function() {
|
434
|
+
ok(!_.isArray(arguments), 'the arguments object is not an array');
|
435
|
+
ok(_.isArray([1, 2, 3]), 'but arrays are');
|
436
|
+
ok(_.isArray(iArray), 'even from another frame');
|
437
|
+
});
|
438
|
+
|
439
|
+
test("isString", function() {
|
440
|
+
ok(!_.isString(document.body), 'the document body is not a string');
|
441
|
+
ok(_.isString([1, 2, 3].join(', ')), 'but strings are');
|
442
|
+
ok(_.isString(iString), 'even from another frame');
|
443
|
+
});
|
444
|
+
|
445
|
+
test("isNumber", function() {
|
446
|
+
ok(!_.isNumber('string'), 'a string is not a number');
|
447
|
+
ok(!_.isNumber(arguments), 'the arguments object is not a number');
|
448
|
+
ok(!_.isNumber(undefined), 'undefined is not a number');
|
449
|
+
ok(_.isNumber(3 * 4 - 7 / 10), 'but numbers are');
|
450
|
+
ok(_.isNumber(NaN), 'NaN *is* a number');
|
451
|
+
ok(_.isNumber(Infinity), 'Infinity is a number');
|
452
|
+
ok(_.isNumber(iNumber), 'even from another frame');
|
453
|
+
ok(!_.isNumber('1'), 'numeric strings are not numbers');
|
454
|
+
});
|
455
|
+
|
456
|
+
test("isBoolean", function() {
|
457
|
+
ok(!_.isBoolean(2), 'a number is not a boolean');
|
458
|
+
ok(!_.isBoolean("string"), 'a string is not a boolean');
|
459
|
+
ok(!_.isBoolean("false"), 'the string "false" is not a boolean');
|
460
|
+
ok(!_.isBoolean("true"), 'the string "true" is not a boolean');
|
461
|
+
ok(!_.isBoolean(arguments), 'the arguments object is not a boolean');
|
462
|
+
ok(!_.isBoolean(undefined), 'undefined is not a boolean');
|
463
|
+
ok(!_.isBoolean(NaN), 'NaN is not a boolean');
|
464
|
+
ok(!_.isBoolean(null), 'null is not a boolean');
|
465
|
+
ok(_.isBoolean(true), 'but true is');
|
466
|
+
ok(_.isBoolean(false), 'and so is false');
|
467
|
+
ok(_.isBoolean(iBoolean), 'even from another frame');
|
468
|
+
});
|
469
|
+
|
470
|
+
test("isFunction", function() {
|
471
|
+
ok(!_.isFunction([1, 2, 3]), 'arrays are not functions');
|
472
|
+
ok(!_.isFunction('moe'), 'strings are not functions');
|
473
|
+
ok(_.isFunction(_.isFunction), 'but functions are');
|
474
|
+
ok(_.isFunction(iFunction), 'even from another frame');
|
475
|
+
});
|
476
|
+
|
477
|
+
test("isDate", function() {
|
478
|
+
ok(!_.isDate(100), 'numbers are not dates');
|
479
|
+
ok(!_.isDate({}), 'objects are not dates');
|
480
|
+
ok(_.isDate(new Date()), 'but dates are');
|
481
|
+
ok(_.isDate(iDate), 'even from another frame');
|
482
|
+
});
|
483
|
+
|
484
|
+
test("isRegExp", function() {
|
485
|
+
ok(!_.isRegExp(_.identity), 'functions are not RegExps');
|
486
|
+
ok(_.isRegExp(/identity/), 'but RegExps are');
|
487
|
+
ok(_.isRegExp(iRegExp), 'even from another frame');
|
488
|
+
});
|
489
|
+
|
490
|
+
test("isFinite", function() {
|
491
|
+
ok(!_.isFinite(undefined), 'undefined is not Finite');
|
492
|
+
ok(!_.isFinite(null), 'null is not Finite');
|
493
|
+
ok(!_.isFinite(NaN), 'NaN is not Finite');
|
494
|
+
ok(!_.isFinite(Infinity), 'Infinity is not Finite');
|
495
|
+
ok(!_.isFinite(-Infinity), '-Infinity is not Finite');
|
496
|
+
ok(_.isFinite('12'), 'Numeric strings are numbers');
|
497
|
+
ok(!_.isFinite('1a'), 'Non numeric strings are not numbers');
|
498
|
+
ok(!_.isFinite(''), 'Empty strings are not numbers');
|
499
|
+
var obj = new Number(5);
|
500
|
+
ok(_.isFinite(obj), 'Number instances can be finite');
|
501
|
+
ok(_.isFinite(0), '0 is Finite');
|
502
|
+
ok(_.isFinite(123), 'Ints are Finite');
|
503
|
+
ok(_.isFinite(-12.44), 'Floats are Finite');
|
504
|
+
});
|
505
|
+
|
506
|
+
test("isNaN", function() {
|
507
|
+
ok(!_.isNaN(undefined), 'undefined is not NaN');
|
508
|
+
ok(!_.isNaN(null), 'null is not NaN');
|
509
|
+
ok(!_.isNaN(0), '0 is not NaN');
|
510
|
+
ok(_.isNaN(NaN), 'but NaN is');
|
511
|
+
ok(_.isNaN(iNaN), 'even from another frame');
|
512
|
+
ok(_.isNaN(new Number(NaN)), 'wrapped NaN is still NaN');
|
513
|
+
});
|
514
|
+
|
515
|
+
test("isNull", function() {
|
516
|
+
ok(!_.isNull(undefined), 'undefined is not null');
|
517
|
+
ok(!_.isNull(NaN), 'NaN is not null');
|
518
|
+
ok(_.isNull(null), 'but null is');
|
519
|
+
ok(_.isNull(iNull), 'even from another frame');
|
520
|
+
});
|
521
|
+
|
522
|
+
test("isUndefined", function() {
|
523
|
+
ok(!_.isUndefined(1), 'numbers are defined');
|
524
|
+
ok(!_.isUndefined(null), 'null is defined');
|
525
|
+
ok(!_.isUndefined(false), 'false is defined');
|
526
|
+
ok(!_.isUndefined(NaN), 'NaN is defined');
|
527
|
+
ok(_.isUndefined(), 'nothing is undefined');
|
528
|
+
ok(_.isUndefined(undefined), 'undefined is undefined');
|
529
|
+
ok(_.isUndefined(iUndefined), 'even from another frame');
|
530
|
+
});
|
531
|
+
|
532
|
+
if (window.ActiveXObject) {
|
533
|
+
test("IE host objects", function() {
|
534
|
+
var xml = new ActiveXObject("Msxml2.DOMDocument.3.0");
|
535
|
+
ok(!_.isNumber(xml));
|
536
|
+
ok(!_.isBoolean(xml));
|
537
|
+
ok(!_.isNaN(xml));
|
538
|
+
ok(!_.isFunction(xml));
|
539
|
+
ok(!_.isNull(xml));
|
540
|
+
ok(!_.isUndefined(xml));
|
541
|
+
});
|
542
|
+
}
|
543
|
+
|
544
|
+
test("tap", function() {
|
545
|
+
var intercepted = null;
|
546
|
+
var interceptor = function(obj) { intercepted = obj; };
|
547
|
+
var returned = _.tap(1, interceptor);
|
548
|
+
equal(intercepted, 1, "passes tapped object to interceptor");
|
549
|
+
equal(returned, 1, "returns tapped object");
|
550
|
+
|
551
|
+
returned = _([1,2,3]).chain().
|
552
|
+
map(function(n){ return n * 2; }).
|
553
|
+
max().
|
554
|
+
tap(interceptor).
|
555
|
+
value();
|
556
|
+
ok(returned == 6 && intercepted == 6, 'can use tapped objects in a chain');
|
557
|
+
});
|
558
|
+
|
559
|
+
test("has", function () {
|
560
|
+
var obj = {foo: "bar", func: function () {} };
|
561
|
+
ok (_.has(obj, "foo"), "has() checks that the object has a property.");
|
562
|
+
ok (_.has(obj, "baz") == false, "has() returns false if the object doesn't have the property.");
|
563
|
+
ok (_.has(obj, "func"), "has() works for functions too.");
|
564
|
+
obj.hasOwnProperty = null;
|
565
|
+
ok (_.has(obj, "foo"), "has() works even when the hasOwnProperty method is deleted.");
|
566
|
+
var child = {};
|
567
|
+
child.prototype = obj;
|
568
|
+
ok (_.has(child, "foo") == false, "has() does not check the prototype chain for a property.")
|
569
|
+
});
|
570
|
+
});
|