├── .gitignore
├── .jshintrc
├── .csslintrc
├── LICENSE
├── dist
├── msgBox.min.css
└── msgBox.min.js
├── package.json
├── test
├── msgBox-spec.js
└── chai.js
├── example
└── example.html
├── README.md
├── src
├── msgBox.css
└── msgBox.js
├── scss
├── msgBox.scss
└── .scsslint.yml
├── karma.conf.js
└── Gruntfile.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # IntelliJ project files
2 | /.idea
3 | /node_modules
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "boss":false,
3 | "curly":true,
4 | "eqeqeq":true,
5 | "eqnull":true,
6 | "expr":true,
7 | "immed":true,
8 | "newcap":true,
9 | "noempty":true,
10 | "noarg":true,
11 | "undef":true,
12 | "regexp":true,
13 | "browser":true,
14 | "devel":true,
15 | "node":true
16 | }
--------------------------------------------------------------------------------
/.csslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "adjoining-classes":false,
3 | "box-sizing":false,
4 | "box-model":false,
5 | "compatible-vendor-prefixes":false,
6 | "floats":false,
7 | "font-sizes":false,
8 | "gradients":false,
9 | "important":false,
10 | "known-properties":false,
11 | "outline-none":false,
12 | "qualified-headings":false,
13 | "regex-selectors":false,
14 | "shorthand":false,
15 | "text-indent":false,
16 | "unique-headings":false,
17 | "universal-selector":false,
18 | "unqualified-attributes":false
19 | }
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 reamd
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/dist/msgBox.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * msgbox v1.0.0 (https://github.com/reamd/msgbox.git)
3 | * Copyright 2016 reamd
4 | * Licensed under MIT
5 | */
6 |
7 | *{padding:0;margin:0}.noScroll{overflow:hidden}.ui-dialog{position:fixed;z-index:100;display:none;width:100%;height:100%;box-sizing:border-box;background-color:rgba(0,0,0,.4)}.ui-dialog.show{display:block}.ui-dialog .ui-dialog-cnt{position:relative;top:50%;width:270px;box-sizing:border-box;margin:0 auto;background-color:rgba(253,253,253,.95);border-radius:6px}.ui-dialog .ui-dialog-hd{padding:10px;border-bottom:1px solid #e6e6e6}.ui-dialog .ui-dialog-hd h3{text-align:center}.ui-dialog .ui-dialog-close{float:right;margin-top:-32px}.ui-dialog .ui-dialog-close:before{font-size:26px;color:#00a5e0;cursor:pointer;content:"\00D7"}.ui-dialog .ui-dialog-bd{padding:18px}.ui-dialog .ui-dialog-bd h4{padding-bottom:10px;text-align:center}.ui-dialog .ui-dialog-ft button{width:50%;box-sizing:border-box;padding:10px 0;color:#00a5e0;cursor:pointer;background:#f8f8f8;border:0;border-top:1px solid #e6e6e6;outline:0}.ui-dialog .ui-dialog-ft button:nth-child(2){border-left:1px solid #e6e6e6}.ui-dialog .ui-dialog-ft button.alone{width:99%}
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "msgbox",
3 | "version": "1.0.0",
4 | "description": "原生js写的一个弹窗组件",
5 | "main": "Gruntfile.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/reamd/msgbox.git"
12 | },
13 | "author": "reamd",
14 | "license": "MIT",
15 | "bugs": {
16 | "url": "https://github.com/reamd/msgbox/issues"
17 | },
18 | "homepage": "https://github.com/reamd/msgbox#readme",
19 | "devDependencies": {
20 | "chai": "^3.5.0",
21 | "grunt": "^0.4.5",
22 | "grunt-banner": "^0.6.0",
23 | "grunt-contrib-clean": "^1.0.0",
24 | "grunt-contrib-cssmin": "^0.14.0",
25 | "grunt-contrib-jshint": "^1.0.0",
26 | "grunt-contrib-sass": "^0.9.2",
27 | "grunt-contrib-uglify": "^0.11.1",
28 | "grunt-contrib-watch": "^0.6.1",
29 | "grunt-html": "^6.0.0",
30 | "grunt-karma": "^0.12.1",
31 | "grunt-scss-lint": "^0.3.8",
32 | "karma": "^0.13.21",
33 | "karma-chrome-launcher": "^0.2.2",
34 | "karma-coverage": "^0.5.3",
35 | "karma-firefox-launcher": "^0.1.7",
36 | "karma-mocha": "^0.2.2",
37 | "load-grunt-tasks": "^3.4.0",
38 | "mocha": "^2.4.5",
39 | "time-grunt": "^1.3.0"
40 | },
41 | "dependencies": {}
42 | }
43 |
--------------------------------------------------------------------------------
/test/msgBox-spec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Created by reamd on 2016/2/25.
3 | */
4 | describe("msgBox", function() {
5 | var should = chai.should();
6 | it("should is a object", function() {
7 | var msgbox = new msgBox({});
8 | msgbox.should.be.a('object');
9 | });
10 | it("check it property", function() {
11 | var msgbox = new msgBox({});
12 | msgbox.should.have.property('width').with.equal('');
13 | msgbox.should.have.property('minWidth').with.equal('0');
14 | msgbox.should.have.property('maxWidth').with.equal('100%');
15 | msgbox.should.have.property('height').with.equal('');
16 | msgbox.should.have.property('title').with.equal('');
17 | msgbox.should.have.property('body').with.equal('');
18 | msgbox.should.have.property('btnLabel').with.a('array').with.length(0);
19 | msgbox.should.have.property('visible').with.equal(true);
20 | msgbox.should.have.property('isClose').with.equal(true);
21 | msgbox.should.have.property('openMsg').with.a('function');
22 | msgbox.should.have.property('closeMsg').with.a('function');
23 | msgbox.should.have.property('complete').with.a('function');
24 | msgbox.should.have.property('firstCallback').with.a('function');
25 | msgbox.should.have.property('secondCallback').with.a('function');
26 | });
27 | });
--------------------------------------------------------------------------------
/example/example.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | 弹窗示例
9 |
10 |
11 |
12 | 1111111111111
13 |
14 |
30 |
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # msgBox说明
2 | 原生JavaScript弹窗组件
3 | # msgBox使用说明
4 | - **首先引入库相关的.css .js文件**
5 | - 未压缩版本(src文件夹下)
6 | ```js
7 |
8 |
9 | ```
10 | - 压缩版本(dist文件夹下)
11 | ```js
12 |
13 |
14 | ```
15 | - **控件初始化**
16 | ```js
17 | new msgBox({
18 | width: '200px', //设置弹窗的宽度,不设置的话默认由弹窗内容决定
19 | minWidth: '100px', //设置弹窗的最小宽度,默认0
20 | maxWidth: '300px', //设置弹窗的最大宽度,默认100%
21 | height: '', //设置弹窗的高度,不设置的话默认由弹窗内容决定
22 | title: '提示语', //设置弹窗边框的标题 默认为空
23 | body: '你好
', //设置弹窗内容,可由html模板组成 默认为空
24 | btnLabel: ['确定', '取消'], //设置弹窗底部按钮标题,数组形式,个数最多两个 默认为空
25 | visible: true, //设置弹窗初始化时是否显示,默认为true
26 | isClose: true, //设置弹窗是否显示右上角的关闭功能,默认为true
27 | callback: function() {}, //设置弹窗初始化完成后运行的回调函数,默认为空函数
28 | firstCallback: function() {}, //设置弹窗底部按钮一回调函数,默认为空函数
29 | secondCallback: function() {} //设置弹窗底部按钮二回调函数,默认为关闭弹窗功能的函数
30 | });
31 | ```
32 | - **控件方法**
33 | ```js
34 | //初始化后,通过实例调用
35 | var msg = new msgBox({title: '提示语', body: '你好', visible: false});
36 | msg.openMsg(); //打开弹窗,一般当初始化时visible为false时使用
37 | msg.closeMsg();//关闭弹窗(注意无论调用方法还是手动关闭弹窗,都将销毁弹窗DOM节点,关闭后将无法使用openMsg方法打开)
38 | ```
--------------------------------------------------------------------------------
/src/msgBox.css:
--------------------------------------------------------------------------------
1 | * {
2 | padding: 0;
3 | margin: 0; }
4 |
5 | .noScroll {
6 | overflow: hidden;
7 | }
8 |
9 | .ui-dialog {
10 | position: fixed;
11 | z-index: 100;
12 | display: none;
13 | width: 100%;
14 | height: 100%;
15 | box-sizing: border-box;
16 | background-color: rgba(0, 0, 0, 0.4); }
17 | .ui-dialog.show {
18 | display: block; }
19 | .ui-dialog .ui-dialog-cnt {
20 | position: relative;
21 | top: 50%;
22 | width: 270px;
23 | box-sizing: border-box;
24 | margin: 0 auto;
25 | background-color: rgba(253, 253, 253, 0.95);
26 | border-radius: 6px; }
27 | .ui-dialog .ui-dialog-hd {
28 | padding: 10px;
29 | border-bottom: 1px solid #e6e6e6; }
30 | .ui-dialog .ui-dialog-hd h3 {
31 | text-align: center; }
32 | .ui-dialog .ui-dialog-close {
33 | float: right;
34 | margin-top: -32px; }
35 | .ui-dialog .ui-dialog-close:before {
36 | font-size: 26px;
37 | color: #00a5e0;
38 | cursor: pointer;
39 | content: "\00D7";
40 | }
41 | .ui-dialog .ui-dialog-bd {
42 | padding: 18px; }
43 | .ui-dialog .ui-dialog-bd h4 {
44 | padding-bottom: 10px;
45 | text-align: center; }
46 | .ui-dialog .ui-dialog-ft button {
47 | width: 50%;
48 | box-sizing: border-box;
49 | padding: 10px 0;
50 | color: #00a5e0;
51 | cursor: pointer;
52 | background: transparent;
53 | background-color: #f8f8f8;
54 | border: 0;
55 | border-top: 1px solid #e6e6e6;
56 | outline: none; }
57 | .ui-dialog .ui-dialog-ft button:nth-child(2) {
58 | border-left: 1px solid #e6e6e6; }
59 | .ui-dialog .ui-dialog-ft button.alone {
60 | width: 99%; }
61 |
62 | /*# sourceMappingURL=msgBox.css.map */
63 |
--------------------------------------------------------------------------------
/scss/msgBox.scss:
--------------------------------------------------------------------------------
1 | $border-color: #e6e6e6;
2 | $blue-color: #00a5e0;
3 | $button-back-color: #f8f8f8;
4 | * {
5 | padding: 0;
6 | margin: 0;
7 | }
8 |
9 | .noScroll {
10 | overflow: hidden;
11 | }
12 |
13 | .ui-dialog {
14 | position: fixed;
15 | z-index: 100;
16 | display: none;
17 | width: 100%;
18 | height: 100%;
19 | box-sizing: border-box;
20 | background-color: rgba(0,0,0,.4);
21 | &.show {
22 | display: block;
23 | }
24 | .ui-dialog-cnt {
25 | position: relative;
26 | top: 50%;
27 | width: 270px;
28 | box-sizing: border-box;
29 | margin: 0 auto;
30 | background-color: rgba(253,253,253,.95);
31 | border-radius: 6px;
32 | }
33 | .ui-dialog-hd {
34 | padding: 10px;
35 | border-bottom: 1px solid $border-color;
36 | }
37 | .ui-dialog-hd h3 {
38 | text-align: center;
39 | }
40 | .ui-dialog-close {
41 | float: right;
42 | margin-top: -32px;
43 | }
44 | .ui-dialog-close:before {
45 | font-size: 26px;
46 | color: $blue-color;
47 | cursor: pointer;
48 | content: "\00D7";
49 | }
50 | .ui-dialog-bd {
51 | padding: 18px;
52 | }
53 | .ui-dialog-bd h4 {
54 | padding-bottom: 10px;
55 | text-align: center;
56 | }
57 | .ui-dialog-ft {
58 | button {
59 | width: 50%;
60 | box-sizing: border-box;
61 | padding: 10px 0;
62 | color: $blue-color;
63 | cursor: pointer;
64 | background: transparent;
65 | background-color: $button-back-color;
66 | border: 0;
67 | border-top: 1px solid $border-color;
68 | outline: none;
69 | &:nth-child(2) {border-left: 1px solid $border-color;}
70 | }
71 | button.alone {
72 | width: 99%;
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | // Generated on Thu Feb 25 2016 13:34:18 GMT+0800 (中国标准时间)
3 |
4 | module.exports = function(config) {
5 | config.set({
6 |
7 | // base path that will be used to resolve all patterns (eg. files, exclude)
8 | basePath: '',
9 |
10 |
11 | // frameworks to use
12 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
13 | frameworks: ['mocha'],
14 |
15 |
16 | // list of files / patterns to load in the browser
17 | files: [
18 | 'src/msgBox.js',
19 | 'test/*.js'
20 | ],
21 |
22 |
23 | // list of files to exclude
24 | exclude: [
25 | ],
26 |
27 |
28 | // preprocess matching files before serving them to the browser
29 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
30 | preprocessors: {
31 | 'msgBox.js': ['coverage']
32 | },
33 |
34 |
35 | // test results reporter to use
36 | // possible values: 'dots', 'progress'
37 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter
38 | reporters: ['progress','coverage'],
39 |
40 | coverageReporter: {
41 | type: 'html',
42 | dir: 'test/coverage/'
43 | },
44 |
45 | // web server port
46 | port: 9876,
47 |
48 |
49 | // enable / disable colors in the output (reporters and logs)
50 | colors: true,
51 |
52 |
53 | // level of logging
54 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
55 | logLevel: config.LOG_INFO,
56 |
57 |
58 | // enable / disable watching file and executing tests whenever any file changes
59 | autoWatch: true,
60 |
61 |
62 | // start these browsers
63 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
64 | browsers: ['Chrome'],
65 |
66 |
67 | // Continuous Integration mode
68 | // if true, Karma captures browsers, runs the tests and exits
69 | singleRun: false,
70 |
71 | // Concurrency level
72 | // how many browser should be started simultaneous
73 | concurrency: Infinity
74 | });
75 | };
76 |
--------------------------------------------------------------------------------
/dist/msgBox.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * msgbox v1.0.0 (https://github.com/reamd/msgbox.git)
3 | * Copyright 2016 reamd
4 | * Licensed under MIT
5 | */
6 |
7 | !function(a,b){"use strict";"function"==typeof define&&define.amd?define("msgBox",[],function(){return b}):"object"==typeof exports?module.exports.msgBox=b:a.msgBox=b}("undefined"!=typeof window?window:this,function(a){var b=document.createElement("div"),c=document.createAttribute("class"),d="",e="",f="",g="",h="",i="",j=this;this.width=a.width||"",this.minWidth=a.minWidth||"0",this.maxWidth=a.maxWidth||"100%",this.height=a.height||"",this.title=a.title||"",this.body=a.body||"",this.btnLabel=a.btnLabel||[],this.visible="boolean"!=typeof a.visible||a.visible,this.isClose="boolean"!=typeof a.isClose||a.isClose,this.openMsg=function(){this.classOpt("noScroll",!0),b.setAttribute("class","ui-dialog show")},this.closeMsg=function(){document.body.removeChild(b),this.classOpt("noScroll",!1)},this.complete=a.callback||function(){},this.firstCallback=a.firstCallback||function(){},this.secondCallback=a.secondCallback||function(){j.closeMsg()},this.classOpt=function(a,b){var c=document.body.getAttribute("class"),d="";if(b)if(c){if(c.indexOf(a)>-1)return;c+=" "+a,document.body.setAttribute("class",c)}else document.body.setAttribute("class",a);else c&&c===a?document.body.removeAttribute("class"):(c.indexOf(" "+a+" ")>-1?d=" "+a+" ":c.indexOf(" "+a)>-1?d=" "+a:c.indexOf(a+" ")>-1&&(d=a+" "),document.body.setAttribute("class",c.replace(d,"")))},this.width?(d='style="width:'+this.width+";min-width:"+this.minWidth+";max-width:"+this.maxWidth+'"',this.height&&(d='style="width:'+this.width+";min-width:"+this.minWidth+";max-width:"+this.maxWidth+";height:"+this.height+'"')):this.height&&(d='style="height:'+this.height+'"'),e=""===this.title?"
":""+this.title+"
",h=""+this.body+"
",this.isClose&&(f=''),"[object Array]"===Object.prototype.toString.call(this.btnLabel)&&(1===this.btnLabel.length?i='":this.btnLabel.length>1&&(i='")),this.visible?(c.value="ui-dialog show",this.classOpt("noScroll",!0)):c.value="ui-dialog",b.setAttributeNode(c),b.innerHTML='",document.body.insertBefore(b,document.body.firstChild),b.firstChild.getAttribute("style")?b.firstChild.setAttribute("style",b.firstChild.getAttribute("style")+";margin-top:-"+b.firstChild.offsetHeight/2+"px"):b.firstChild.setAttribute("style","margin-top:-"+b.firstChild.offsetHeight/2+"px"),setTimeout(this.complete,0),setTimeout(function(){j.isClose&&b.firstChild.firstChild.lastChild.addEventListener("click",function(){j.closeMsg()},!1),1===j.btnLabel.length?b.firstChild.childNodes[2].firstChild.addEventListener("click",j.firstCallback,!1):j.btnLabel.length>1&&(b.firstChild.childNodes[2].firstChild.addEventListener("click",j.firstCallback,!1),b.firstChild.childNodes[2].lastChild.addEventListener("click",j.secondCallback,!1))},0)});
--------------------------------------------------------------------------------
/Gruntfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 | module.exports = function(grunt) {
3 |
4 | require('time-grunt')(grunt);
5 | require( "load-grunt-tasks" )( grunt );
6 | // Project configuration.
7 | grunt.initConfig({
8 | pkg: grunt.file.readJSON('package.json'),
9 | banner: '/*!\n' +
10 | ' * <%= pkg.name %> v<%= pkg.version %> (<%= pkg.repository.url %>)\n' +
11 | ' * Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' +
12 | ' * Licensed under MIT\n' +
13 | ' */\n',
14 |
15 | //清空style和js
16 | clean: {
17 | dist: {
18 | src: 'dist/'
19 | },
20 | temp: {
21 | src: ['test/coverage']
22 | }
23 | },
24 |
25 | //js语法检查
26 | jshint: {
27 | files: ['src/*.js'],
28 | options: {
29 | globals:{
30 | jshintrc:'.jshintrc'
31 | }
32 | }
33 | },
34 | //css语法检查
35 | csslint:{
36 | files:['src/*.css'],
37 | options:{
38 | globals:{
39 | csslintrc:'.csslintrc'
40 | }
41 | }
42 | },
43 | //scss语法检查
44 | scsslint: {
45 | options: {
46 | config: 'scss/.scsslint.yml',
47 | reporterOutput: null
48 | },
49 | src: ['scss/*.scss']
50 | },
51 | //html语法检查
52 | htmllint: {
53 | options: {
54 | ignore: [
55 | 'Element “img” is missing required attribute “src”.',
56 | 'Bad value “X-UA-Compatible” for attribute “http-equiv” on element “meta”.',
57 | 'Attribute “autocomplete” not allowed on element “input” at this point.',
58 | 'Attribute “autocomplete” not allowed on element “button” at this point.',
59 | 'Element “div” not allowed as child of element “progress” in this context. (Suppressing further errors from this subtree.)',
60 | 'Consider using the “h1” element as a top-level heading only (all “h1” elements are treated as top-level headings by many screen readers and other tools).',
61 | 'The “datetime” input type is not supported in all browsers. Please be sure to test, and consider using a polyfill.'
62 | ]
63 | },
64 | src: 'example/*.html'
65 | },
66 |
67 | //执行scss编译
68 | sass: {
69 | dist: {
70 | files:[{
71 | expand: true,
72 | cwd: 'scss',
73 | src: ['*.scss'],
74 | dest: 'src/',
75 | ext: '.css'
76 | }]
77 | }
78 | },
79 | //js压缩
80 | uglify: {
81 | options: {
82 | //beautify:true,
83 | //mangle: false //不混淆
84 | //banner: '<%= banner %>'
85 | },
86 | build: {
87 | files: [{
88 | expand: true,
89 | cwd: 'src/',
90 | src: ['*.js'],
91 | dest: 'dist/',
92 | ext: '.min.js'
93 | }]
94 | }
95 | },
96 | //css压缩合并
97 | cssmin: {
98 | build: {
99 | files: [{
100 | expand: true,
101 | cwd: 'src/',
102 | src: '*.css',
103 | dest: 'dist/',
104 | ext: '.min.css'
105 | }]
106 | }
107 | },
108 |
109 | //为文件插入banner
110 | usebanner: {
111 | options: {
112 | position: 'top',
113 | banner: '<%= banner %>'
114 | },
115 | files: {
116 | src: ['dist/*.css', 'dist/*.js']
117 | }
118 | },
119 | //自动化单元测试
120 | karma: {
121 | unit: {
122 | configFile: 'karma.conf.js',
123 | autoWatch: true
124 | }
125 | },
126 | //监控,自动化
127 | watch:{
128 | scss: {
129 | files: ['scss/*.scss'],
130 | tasks: ['sass']
131 | }
132 | }
133 |
134 | });
135 |
136 | // 语法校验
137 | grunt.registerTask('check', ['jshint', 'scsslint', 'htmllint']);
138 |
139 | // 推送版本前执行的工作
140 | grunt.registerTask('default', ['clean:dist', 'uglify', 'cssmin', 'usebanner']);
141 |
142 | };
--------------------------------------------------------------------------------
/src/msgBox.js:
--------------------------------------------------------------------------------
1 | //UMD通用接口
2 | (function (root, factory) {
3 | "use strict";
4 | if (typeof define === 'function' && define.amd) {
5 | // AMD
6 | define('msgBox', [], function () {
7 | return factory;
8 | });
9 | } else if (typeof exports === 'object') {
10 | // Node.js
11 | module.exports.msgBox = factory;
12 |
13 | } else {
14 | // Browser globals
15 | root.msgBox = factory;
16 | }
17 | }(typeof window !== "undefined" ? window : this, function (opt) {
18 | var newNode = document.createElement('div'),
19 | newClass = document.createAttribute('class'),
20 | cntAttr = '',
21 | h3Node = '',
22 | closeNode = '',
23 | cntTitleNode = '',
24 | cntBodyNode = '',
25 | btnNode = '',
26 | _self = this;
27 |
28 | //构造函数的数据结构
29 | this.width = opt.width || '';
30 | this.minWidth = opt.minWidth || '0';
31 | this.maxWidth = opt.maxWidth || '100%';
32 | this.height = opt.height || '';
33 |
34 | this.title = opt.title || '';
35 | this.body = opt.body || '';
36 | this.btnLabel = opt.btnLabel || [];
37 |
38 | this.visible = typeof opt.visible === 'boolean' ? opt.visible : true;
39 | this.isClose = typeof opt.isClose === 'boolean' ? opt.isClose : true;
40 |
41 | this.openMsg = function () {
42 | this.classOpt('noScroll',true);
43 | newNode.setAttribute('class', 'ui-dialog show');
44 | };
45 | this.closeMsg = function () {
46 | document.body.removeChild(newNode);
47 | this.classOpt('noScroll',false);
48 | };
49 |
50 | this.complete = opt.callback || function () {
51 | };
52 | this.firstCallback = opt.firstCallback || function () {
53 | };
54 | this.secondCallback = opt.secondCallback || function () {
55 | _self.closeMsg();
56 | };
57 | //增加class相关方法
58 | this.classOpt = function(clsName, flag){
59 | var className = document.body.getAttribute('class'),
60 | resName = '';
61 | if(flag){//新增
62 | if(className){//body中存在class
63 | if(className.indexOf(clsName) > -1){
64 | return;
65 | }else {
66 | className += ' ' + clsName;
67 | document.body.setAttribute('class', className);
68 | }
69 | }else {
70 | document.body.setAttribute('class', clsName);
71 | }
72 | }else {//移除
73 | if(className && className === clsName){
74 | document.body.removeAttribute('class');
75 | }else {
76 | if(className.indexOf(' '+ clsName +' ') > -1){
77 | resName = ' '+ clsName +' ';
78 | }else if(className.indexOf(' '+ clsName) > -1){
79 | resName = ' '+ clsName;
80 | }else if(className.indexOf(clsName+' ') > -1){
81 | resName = clsName+' ';
82 | }
83 | document.body.setAttribute('class', className.replace(resName,''));
84 | }
85 | }
86 | };
87 |
88 | if (this.width) {
89 | cntAttr = 'style="width:' + this.width + ';min-width:' + this.minWidth + ';max-width:' + this.maxWidth + '"';
90 | if (this.height) {
91 | cntAttr = 'style="width:' + this.width + ';min-width:' + this.minWidth + ';max-width:' + this.maxWidth + ';height:' + this.height + '"';
92 | }
93 | } else if (this.height) {
94 | cntAttr = 'style="height:' + this.height + '"';
95 | }
96 | if(this.title === '') {
97 | h3Node = '
';
98 | }else {
99 | h3Node = '' + this.title + '
';
100 | }
101 | cntBodyNode = '' + this.body + '
';
102 |
103 | if (this.isClose) {
104 | closeNode = '';
105 | }
106 | if (Object.prototype.toString.call(this.btnLabel) === "[object Array]") {
107 | if (this.btnLabel.length === 1) {
108 | btnNode = '';
109 | } else if (this.btnLabel.length > 1) {
110 | btnNode = '' +
111 | '';
112 | }
113 | }
114 |
115 | if (this.visible) {
116 | newClass.value = 'ui-dialog show';
117 | this.classOpt('noScroll',true);
118 | } else {
119 | newClass.value = 'ui-dialog';
120 | }
121 | newNode.setAttributeNode(newClass);
122 | newNode.innerHTML = '' +
123 | '
' +
124 | h3Node + closeNode +
125 | '
' +
126 | '
' +
127 | cntTitleNode + cntBodyNode +
128 | '
' +
129 | '
' +
130 | btnNode +
131 | '
' +
132 | '
';
133 | document.body.insertBefore(newNode, document.body.firstChild);
134 | //获取弹窗高度,然后设置margin-top
135 | if (!!newNode.firstChild.getAttribute('style')) {
136 | newNode.firstChild.setAttribute('style', newNode.firstChild.getAttribute('style') + ';margin-top:-' + newNode.firstChild.offsetHeight / 2 + 'px');
137 | } else {
138 | newNode.firstChild.setAttribute('style', 'margin-top:-' + newNode.firstChild.offsetHeight / 2 + 'px');
139 | }
140 | setTimeout(this.complete, 0);
141 | setTimeout(function () {
142 | if (_self.isClose) {
143 | newNode.firstChild.firstChild.lastChild.addEventListener('click', function () {
144 | _self.closeMsg();
145 | }, false);
146 | }
147 | if (_self.btnLabel.length === 1) {
148 | newNode.firstChild.childNodes[2].firstChild.addEventListener('click', _self.firstCallback, false);
149 | } else if (_self.btnLabel.length > 1) {
150 | newNode.firstChild.childNodes[2].firstChild.addEventListener('click', _self.firstCallback, false);
151 | newNode.firstChild.childNodes[2].lastChild.addEventListener('click', _self.secondCallback, false);
152 | }
153 | }, 0);
154 | }));
--------------------------------------------------------------------------------
/scss/.scsslint.yml:
--------------------------------------------------------------------------------
1 | scss_files: "scss/*.scss"
2 |
3 | linters:
4 | BangFormat:
5 | enabled: true
6 | space_before_bang: true
7 | space_after_bang: false
8 | #include: []
9 | #exclude: ['_normalize.scss']
10 |
11 | BorderZero:
12 | enabled: true
13 |
14 | ColorKeyword:
15 | enabled: true
16 |
17 | Comment:
18 | enabled: true
19 |
20 | DebugStatement:
21 | enabled: true
22 |
23 | DeclarationOrder:
24 | enabled: false
25 |
26 | DuplicateProperty:
27 | enabled: true
28 |
29 | ElsePlacement:
30 | enabled: true
31 | style: same_line # or 'new_line'
32 |
33 | EmptyLineBetweenBlocks:
34 | enabled: false
35 | ignore_single_line_blocks: true
36 |
37 | EmptyRule:
38 | enabled: true
39 |
40 | FinalNewline:
41 | enabled: true
42 | present: true
43 |
44 | HexLength:
45 | enabled: true
46 | style: short # or 'long'
47 |
48 | HexNotation:
49 | enabled: true
50 | style: lowercase # or 'uppercase'
51 |
52 | HexValidation:
53 | enabled: true
54 |
55 | IdSelector:
56 | enabled: true
57 |
58 | ImportPath:
59 | enabled: true
60 | leading_underscore: false
61 | filename_extension: false
62 |
63 | Indentation:
64 | enabled: true
65 | character: space # or 'tab'
66 | width: 2
67 |
68 | LeadingZero:
69 | enabled: false
70 | style: exclude_zero # or 'include_zero'
71 |
72 | MergeableSelector:
73 | enabled: false
74 | force_nesting: true
75 |
76 | NameFormat:
77 | enabled: true
78 | allow_leading_underscore: true
79 | convention: hyphenated_lowercase # or 'BEM', or a regex pattern
80 |
81 | NestingDepth:
82 | enabled: false
83 |
84 | PlaceholderInExtend:
85 | enabled: false
86 |
87 | PropertySortOrder:
88 | enabled: true
89 | ignore_unspecified: false
90 | severity: warning
91 | order: [
92 | "position",
93 | "top",
94 | "right",
95 | "bottom",
96 | "left",
97 | "z-index",
98 | "display",
99 | "float",
100 | "width",
101 | "min-width",
102 | "max-width",
103 | "height",
104 | "min-height",
105 | "max-height",
106 | "-webkit-box-sizing",
107 | "-moz-box-sizing",
108 | "box-sizing",
109 | "-webkit-appearance",
110 | "flex",
111 | "flex-direction",
112 | "flex-flow",
113 | "flex-order",
114 | "flex-pack",
115 | "flex-align",
116 | "padding",
117 | "padding-top",
118 | "padding-right",
119 | "padding-bottom",
120 | "padding-left",
121 | "margin",
122 | "margin-top",
123 | "margin-right",
124 | "margin-bottom",
125 | "margin-left",
126 | "overflow",
127 | "overflow-x",
128 | "overflow-y",
129 | "-webkit-overflow-scrolling",
130 | "-ms-overflow-x",
131 | "-ms-overflow-y",
132 | "-ms-overflow-style",
133 | "clip",
134 | "clear",
135 | "font",
136 | "font-family",
137 | "font-size",
138 | "font-style",
139 | "font-weight",
140 | "font-variant",
141 | "font-size-adjust",
142 | "font-stretch",
143 | "font-effect",
144 | "font-emphasize",
145 | "font-emphasize-position",
146 | "font-emphasize-style",
147 | "font-smooth",
148 | "-webkit-hyphens",
149 | "-moz-hyphens",
150 | "hyphens",
151 | "line-height",
152 | "color",
153 | "text-align",
154 | "-webkit-text-align-last",
155 | "-moz-text-align-last",
156 | "-ms-text-align-last",
157 | "text-align-last",
158 | "text-emphasis",
159 | "text-emphasis-color",
160 | "text-emphasis-style",
161 | "text-emphasis-position",
162 | "text-decoration",
163 | "text-indent",
164 | "text-justify",
165 | "text-outline",
166 | "-ms-text-overflow",
167 | "text-overflow",
168 | "text-overflow-ellipsis",
169 | "text-overflow-mode",
170 | "text-shadow",
171 | "text-transform",
172 | "text-wrap",
173 | "-webkit-text-size-adjust",
174 | "-ms-text-size-adjust",
175 | "letter-spacing",
176 | "-ms-word-break",
177 | "word-break",
178 | "word-spacing",
179 | "-ms-word-wrap",
180 | "word-wrap",
181 | "-moz-tab-size",
182 | "-o-tab-size",
183 | "tab-size",
184 | "white-space",
185 | "vertical-align",
186 | "list-style",
187 | "list-style-position",
188 | "list-style-type",
189 | "list-style-image",
190 | "pointer-events",
191 | "-ms-touch-action",
192 | "touch-action",
193 | "cursor",
194 | "visibility",
195 | "zoom",
196 | "table-layout",
197 | "empty-cells",
198 | "caption-side",
199 | "border-spacing",
200 | "border-collapse",
201 | "content",
202 | "quotes",
203 | "counter-reset",
204 | "counter-increment",
205 | "resize",
206 | "-webkit-user-select",
207 | "-moz-user-select",
208 | "-ms-user-select",
209 | "-o-user-select",
210 | "user-select",
211 | "nav-index",
212 | "nav-up",
213 | "nav-right",
214 | "nav-down",
215 | "nav-left",
216 | "background",
217 | "background-color",
218 | "background-image",
219 | "-ms-filter:\\'progid:DXImageTransform.Microsoft.gradient",
220 | "filter:progid:DXImageTransform.Microsoft.gradient",
221 | "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader",
222 | "filter",
223 | "background-repeat",
224 | "background-attachment",
225 | "background-position",
226 | "background-position-x",
227 | "background-position-y",
228 | "-webkit-background-clip",
229 | "-moz-background-clip",
230 | "background-clip",
231 | "background-origin",
232 | "-webkit-background-size",
233 | "-moz-background-size",
234 | "-o-background-size",
235 | "background-size",
236 | "border",
237 | "border-color",
238 | "border-style",
239 | "border-width",
240 | "border-top",
241 | "border-top-color",
242 | "border-top-style",
243 | "border-top-width",
244 | "border-right",
245 | "border-right-color",
246 | "border-right-style",
247 | "border-right-width",
248 | "border-bottom",
249 | "border-bottom-color",
250 | "border-bottom-style",
251 | "border-bottom-width",
252 | "border-left",
253 | "border-left-color",
254 | "border-left-style",
255 | "border-left-width",
256 | "border-radius",
257 | "border-top-left-radius",
258 | "border-top-right-radius",
259 | "border-bottom-right-radius",
260 | "border-bottom-left-radius",
261 | "-webkit-border-image",
262 | "-moz-border-image",
263 | "-o-border-image",
264 | "border-image",
265 | "-webkit-border-image-source",
266 | "-moz-border-image-source",
267 | "-o-border-image-source",
268 | "border-image-source",
269 | "-webkit-border-image-slice",
270 | "-moz-border-image-slice",
271 | "-o-border-image-slice",
272 | "border-image-slice",
273 | "-webkit-border-image-width",
274 | "-moz-border-image-width",
275 | "-o-border-image-width",
276 | "border-image-width",
277 | "-webkit-border-image-outset",
278 | "-moz-border-image-outset",
279 | "-o-border-image-outset",
280 | "border-image-outset",
281 | "-webkit-border-image-repeat",
282 | "-moz-border-image-repeat",
283 | "-o-border-image-repeat",
284 | "border-image-repeat",
285 | "outline",
286 | "outline-width",
287 | "outline-style",
288 | "outline-color",
289 | "outline-offset",
290 | "-webkit-box-shadow",
291 | "-moz-box-shadow",
292 | "box-shadow",
293 | "filter:progid:DXImageTransform.Microsoft.Alpha(Opacity",
294 | "-ms-filter:\\'progid:DXImageTransform.Microsoft.Alpha",
295 | "opacity",
296 | "-ms-interpolation-mode",
297 | "-webkit-transition",
298 | "-moz-transition",
299 | "-ms-transition",
300 | "-o-transition",
301 | "transition",
302 | "-webkit-transition-delay",
303 | "-moz-transition-delay",
304 | "-ms-transition-delay",
305 | "-o-transition-delay",
306 | "transition-delay",
307 | "-webkit-transition-timing-function",
308 | "-moz-transition-timing-function",
309 | "-ms-transition-timing-function",
310 | "-o-transition-timing-function",
311 | "transition-timing-function",
312 | "-webkit-transition-duration",
313 | "-moz-transition-duration",
314 | "-ms-transition-duration",
315 | "-o-transition-duration",
316 | "transition-duration",
317 | "-webkit-transition-property",
318 | "-moz-transition-property",
319 | "-ms-transition-property",
320 | "-o-transition-property",
321 | "transition-property",
322 | "-webkit-transform",
323 | "-moz-transform",
324 | "-ms-transform",
325 | "-o-transform",
326 | "transform",
327 | "-webkit-transform-origin",
328 | "-moz-transform-origin",
329 | "-ms-transform-origin",
330 | "-o-transform-origin",
331 | "transform-origin",
332 | "-webkit-animation",
333 | "-moz-animation",
334 | "-ms-animation",
335 | "-o-animation",
336 | "animation",
337 | "-webkit-animation-name",
338 | "-moz-animation-name",
339 | "-ms-animation-name",
340 | "-o-animation-name",
341 | "animation-name",
342 | "-webkit-animation-duration",
343 | "-moz-animation-duration",
344 | "-ms-animation-duration",
345 | "-o-animation-duration",
346 | "animation-duration",
347 | "-webkit-animation-play-state",
348 | "-moz-animation-play-state",
349 | "-ms-animation-play-state",
350 | "-o-animation-play-state",
351 | "animation-play-state",
352 | "-webkit-animation-timing-function",
353 | "-moz-animation-timing-function",
354 | "-ms-animation-timing-function",
355 | "-o-animation-timing-function",
356 | "animation-timing-function",
357 | "-webkit-animation-delay",
358 | "-moz-animation-delay",
359 | "-ms-animation-delay",
360 | "-o-animation-delay",
361 | "animation-delay",
362 | "-webkit-animation-iteration-count",
363 | "-moz-animation-iteration-count",
364 | "-ms-animation-iteration-count",
365 | "-o-animation-iteration-count",
366 | "animation-iteration-count",
367 | "-webkit-animation-direction",
368 | "-moz-animation-direction",
369 | "-ms-animation-direction",
370 | "-o-animation-direction",
371 | "animation-direction"
372 | ]
373 |
374 | PropertySpelling:
375 | enabled: true
376 | extra_properties: []
377 |
378 | QualifyingElement:
379 | enabled: false
380 | allow_element_with_attribute: false
381 | allow_element_with_class: false
382 | allow_element_with_id: false
383 |
384 | SelectorDepth:
385 | enabled: false
386 |
387 | SelectorFormat:
388 | enabled: true
389 | convention: hyphenated_lowercase # or 'BEM', or 'snake_case', or 'camel_case', or a regex pattern
390 |
391 | Shorthand:
392 | enabled: true
393 |
394 | SingleLinePerProperty:
395 | enabled: true
396 | allow_single_line_rule_sets: true
397 |
398 | SingleLinePerSelector:
399 | enabled: false
400 |
401 | SpaceAfterComma:
402 | enabled: false
403 |
404 | SpaceAfterPropertyColon:
405 | enabled: true
406 | style: at_least_one_space # or 'no_space', or 'at_least_one_space', or 'aligned'
407 |
408 | SpaceAfterPropertyName:
409 | enabled: true
410 |
411 | SpaceBeforeBrace:
412 | enabled: true
413 | style: space
414 | allow_single_line_padding: true
415 |
416 | SpaceBetweenParens:
417 | enabled: true
418 | spaces: 0
419 |
420 | StringQuotes:
421 | enabled: true
422 | style: double_quotes
423 |
424 | TrailingSemicolon:
425 | enabled: true
426 |
427 | TrailingZero:
428 | enabled: false
429 |
430 | UnnecessaryMantissa:
431 | enabled: true
432 |
433 | UnnecessaryParentReference:
434 | enabled: true
435 |
436 | UrlFormat:
437 | enabled: true
438 |
439 | UrlQuotes:
440 | enabled: true
441 |
442 | VendorPrefixes:
443 | enabled: true
444 | identifier_list: base
445 |
446 | ZeroUnit:
447 | enabled: true
448 |
449 | Compass::*:
450 | enabled: false
451 |
--------------------------------------------------------------------------------
/test/chai.js:
--------------------------------------------------------------------------------
1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.chai = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o
8 | * MIT Licensed
9 | */
10 |
11 | var used = []
12 | , exports = module.exports = {};
13 |
14 | /*!
15 | * Chai version
16 | */
17 |
18 | exports.version = '3.5.0';
19 |
20 | /*!
21 | * Assertion Error
22 | */
23 |
24 | exports.AssertionError = require('assertion-error');
25 |
26 | /*!
27 | * Utils for plugins (not exported)
28 | */
29 |
30 | var util = require('./chai/utils');
31 |
32 | /**
33 | * # .use(function)
34 | *
35 | * Provides a way to extend the internals of Chai
36 | *
37 | * @param {Function}
38 | * @returns {this} for chaining
39 | * @api public
40 | */
41 |
42 | exports.use = function (fn) {
43 | if (!~used.indexOf(fn)) {
44 | fn(this, util);
45 | used.push(fn);
46 | }
47 |
48 | return this;
49 | };
50 |
51 | /*!
52 | * Utility Functions
53 | */
54 |
55 | exports.util = util;
56 |
57 | /*!
58 | * Configuration
59 | */
60 |
61 | var config = require('./chai/config');
62 | exports.config = config;
63 |
64 | /*!
65 | * Primary `Assertion` prototype
66 | */
67 |
68 | var assertion = require('./chai/assertion');
69 | exports.use(assertion);
70 |
71 | /*!
72 | * Core Assertions
73 | */
74 |
75 | var core = require('./chai/core/assertions');
76 | exports.use(core);
77 |
78 | /*!
79 | * Expect interface
80 | */
81 |
82 | var expect = require('./chai/interface/expect');
83 | exports.use(expect);
84 |
85 | /*!
86 | * Should interface
87 | */
88 |
89 | var should = require('./chai/interface/should');
90 | exports.use(should);
91 |
92 | /*!
93 | * Assert interface
94 | */
95 |
96 | var assert = require('./chai/interface/assert');
97 | exports.use(assert);
98 |
99 | },{"./chai/assertion":3,"./chai/config":4,"./chai/core/assertions":5,"./chai/interface/assert":6,"./chai/interface/expect":7,"./chai/interface/should":8,"./chai/utils":22,"assertion-error":30}],3:[function(require,module,exports){
100 | /*!
101 | * chai
102 | * http://chaijs.com
103 | * Copyright(c) 2011-2014 Jake Luer
104 | * MIT Licensed
105 | */
106 |
107 | var config = require('./config');
108 |
109 | module.exports = function (_chai, util) {
110 | /*!
111 | * Module dependencies.
112 | */
113 |
114 | var AssertionError = _chai.AssertionError
115 | , flag = util.flag;
116 |
117 | /*!
118 | * Module export.
119 | */
120 |
121 | _chai.Assertion = Assertion;
122 |
123 | /*!
124 | * Assertion Constructor
125 | *
126 | * Creates object for chaining.
127 | *
128 | * @api private
129 | */
130 |
131 | function Assertion (obj, msg, stack) {
132 | flag(this, 'ssfi', stack || arguments.callee);
133 | flag(this, 'object', obj);
134 | flag(this, 'message', msg);
135 | }
136 |
137 | Object.defineProperty(Assertion, 'includeStack', {
138 | get: function() {
139 | console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');
140 | return config.includeStack;
141 | },
142 | set: function(value) {
143 | console.warn('Assertion.includeStack is deprecated, use chai.config.includeStack instead.');
144 | config.includeStack = value;
145 | }
146 | });
147 |
148 | Object.defineProperty(Assertion, 'showDiff', {
149 | get: function() {
150 | console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');
151 | return config.showDiff;
152 | },
153 | set: function(value) {
154 | console.warn('Assertion.showDiff is deprecated, use chai.config.showDiff instead.');
155 | config.showDiff = value;
156 | }
157 | });
158 |
159 | Assertion.addProperty = function (name, fn) {
160 | util.addProperty(this.prototype, name, fn);
161 | };
162 |
163 | Assertion.addMethod = function (name, fn) {
164 | util.addMethod(this.prototype, name, fn);
165 | };
166 |
167 | Assertion.addChainableMethod = function (name, fn, chainingBehavior) {
168 | util.addChainableMethod(this.prototype, name, fn, chainingBehavior);
169 | };
170 |
171 | Assertion.overwriteProperty = function (name, fn) {
172 | util.overwriteProperty(this.prototype, name, fn);
173 | };
174 |
175 | Assertion.overwriteMethod = function (name, fn) {
176 | util.overwriteMethod(this.prototype, name, fn);
177 | };
178 |
179 | Assertion.overwriteChainableMethod = function (name, fn, chainingBehavior) {
180 | util.overwriteChainableMethod(this.prototype, name, fn, chainingBehavior);
181 | };
182 |
183 | /**
184 | * ### .assert(expression, message, negateMessage, expected, actual, showDiff)
185 | *
186 | * Executes an expression and check expectations. Throws AssertionError for reporting if test doesn't pass.
187 | *
188 | * @name assert
189 | * @param {Philosophical} expression to be tested
190 | * @param {String|Function} message or function that returns message to display if expression fails
191 | * @param {String|Function} negatedMessage or function that returns negatedMessage to display if negated expression fails
192 | * @param {Mixed} expected value (remember to check for negation)
193 | * @param {Mixed} actual (optional) will default to `this.obj`
194 | * @param {Boolean} showDiff (optional) when set to `true`, assert will display a diff in addition to the message if expression fails
195 | * @api private
196 | */
197 |
198 | Assertion.prototype.assert = function (expr, msg, negateMsg, expected, _actual, showDiff) {
199 | var ok = util.test(this, arguments);
200 | if (true !== showDiff) showDiff = false;
201 | if (true !== config.showDiff) showDiff = false;
202 |
203 | if (!ok) {
204 | var msg = util.getMessage(this, arguments)
205 | , actual = util.getActual(this, arguments);
206 | throw new AssertionError(msg, {
207 | actual: actual
208 | , expected: expected
209 | , showDiff: showDiff
210 | }, (config.includeStack) ? this.assert : flag(this, 'ssfi'));
211 | }
212 | };
213 |
214 | /*!
215 | * ### ._obj
216 | *
217 | * Quick reference to stored `actual` value for plugin developers.
218 | *
219 | * @api private
220 | */
221 |
222 | Object.defineProperty(Assertion.prototype, '_obj',
223 | { get: function () {
224 | return flag(this, 'object');
225 | }
226 | , set: function (val) {
227 | flag(this, 'object', val);
228 | }
229 | });
230 | };
231 |
232 | },{"./config":4}],4:[function(require,module,exports){
233 | module.exports = {
234 |
235 | /**
236 | * ### config.includeStack
237 | *
238 | * User configurable property, influences whether stack trace
239 | * is included in Assertion error message. Default of false
240 | * suppresses stack trace in the error message.
241 | *
242 | * chai.config.includeStack = true; // enable stack on error
243 | *
244 | * @param {Boolean}
245 | * @api public
246 | */
247 |
248 | includeStack: false,
249 |
250 | /**
251 | * ### config.showDiff
252 | *
253 | * User configurable property, influences whether or not
254 | * the `showDiff` flag should be included in the thrown
255 | * AssertionErrors. `false` will always be `false`; `true`
256 | * will be true when the assertion has requested a diff
257 | * be shown.
258 | *
259 | * @param {Boolean}
260 | * @api public
261 | */
262 |
263 | showDiff: true,
264 |
265 | /**
266 | * ### config.truncateThreshold
267 | *
268 | * User configurable property, sets length threshold for actual and
269 | * expected values in assertion errors. If this threshold is exceeded, for
270 | * example for large data structures, the value is replaced with something
271 | * like `[ Array(3) ]` or `{ Object (prop1, prop2) }`.
272 | *
273 | * Set it to zero if you want to disable truncating altogether.
274 | *
275 | * This is especially userful when doing assertions on arrays: having this
276 | * set to a reasonable large value makes the failure messages readily
277 | * inspectable.
278 | *
279 | * chai.config.truncateThreshold = 0; // disable truncating
280 | *
281 | * @param {Number}
282 | * @api public
283 | */
284 |
285 | truncateThreshold: 40
286 |
287 | };
288 |
289 | },{}],5:[function(require,module,exports){
290 | /*!
291 | * chai
292 | * http://chaijs.com
293 | * Copyright(c) 2011-2014 Jake Luer
294 | * MIT Licensed
295 | */
296 |
297 | module.exports = function (chai, _) {
298 | var Assertion = chai.Assertion
299 | , toString = Object.prototype.toString
300 | , flag = _.flag;
301 |
302 | /**
303 | * ### Language Chains
304 | *
305 | * The following are provided as chainable getters to
306 | * improve the readability of your assertions. They
307 | * do not provide testing capabilities unless they
308 | * have been overwritten by a plugin.
309 | *
310 | * **Chains**
311 | *
312 | * - to
313 | * - be
314 | * - been
315 | * - is
316 | * - that
317 | * - which
318 | * - and
319 | * - has
320 | * - have
321 | * - with
322 | * - at
323 | * - of
324 | * - same
325 | *
326 | * @name language chains
327 | * @namespace BDD
328 | * @api public
329 | */
330 |
331 | [ 'to', 'be', 'been'
332 | , 'is', 'and', 'has', 'have'
333 | , 'with', 'that', 'which', 'at'
334 | , 'of', 'same' ].forEach(function (chain) {
335 | Assertion.addProperty(chain, function () {
336 | return this;
337 | });
338 | });
339 |
340 | /**
341 | * ### .not
342 | *
343 | * Negates any of assertions following in the chain.
344 | *
345 | * expect(foo).to.not.equal('bar');
346 | * expect(goodFn).to.not.throw(Error);
347 | * expect({ foo: 'baz' }).to.have.property('foo')
348 | * .and.not.equal('bar');
349 | *
350 | * @name not
351 | * @namespace BDD
352 | * @api public
353 | */
354 |
355 | Assertion.addProperty('not', function () {
356 | flag(this, 'negate', true);
357 | });
358 |
359 | /**
360 | * ### .deep
361 | *
362 | * Sets the `deep` flag, later used by the `equal` and
363 | * `property` assertions.
364 | *
365 | * expect(foo).to.deep.equal({ bar: 'baz' });
366 | * expect({ foo: { bar: { baz: 'quux' } } })
367 | * .to.have.deep.property('foo.bar.baz', 'quux');
368 | *
369 | * `.deep.property` special characters can be escaped
370 | * by adding two slashes before the `.` or `[]`.
371 | *
372 | * var deepCss = { '.link': { '[target]': 42 }};
373 | * expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42);
374 | *
375 | * @name deep
376 | * @namespace BDD
377 | * @api public
378 | */
379 |
380 | Assertion.addProperty('deep', function () {
381 | flag(this, 'deep', true);
382 | });
383 |
384 | /**
385 | * ### .any
386 | *
387 | * Sets the `any` flag, (opposite of the `all` flag)
388 | * later used in the `keys` assertion.
389 | *
390 | * expect(foo).to.have.any.keys('bar', 'baz');
391 | *
392 | * @name any
393 | * @namespace BDD
394 | * @api public
395 | */
396 |
397 | Assertion.addProperty('any', function () {
398 | flag(this, 'any', true);
399 | flag(this, 'all', false)
400 | });
401 |
402 |
403 | /**
404 | * ### .all
405 | *
406 | * Sets the `all` flag (opposite of the `any` flag)
407 | * later used by the `keys` assertion.
408 | *
409 | * expect(foo).to.have.all.keys('bar', 'baz');
410 | *
411 | * @name all
412 | * @namespace BDD
413 | * @api public
414 | */
415 |
416 | Assertion.addProperty('all', function () {
417 | flag(this, 'all', true);
418 | flag(this, 'any', false);
419 | });
420 |
421 | /**
422 | * ### .a(type)
423 | *
424 | * The `a` and `an` assertions are aliases that can be
425 | * used either as language chains or to assert a value's
426 | * type.
427 | *
428 | * // typeof
429 | * expect('test').to.be.a('string');
430 | * expect({ foo: 'bar' }).to.be.an('object');
431 | * expect(null).to.be.a('null');
432 | * expect(undefined).to.be.an('undefined');
433 | * expect(new Error).to.be.an('error');
434 | * expect(new Promise).to.be.a('promise');
435 | * expect(new Float32Array()).to.be.a('float32array');
436 | * expect(Symbol()).to.be.a('symbol');
437 | *
438 | * // es6 overrides
439 | * expect({[Symbol.toStringTag]:()=>'foo'}).to.be.a('foo');
440 | *
441 | * // language chain
442 | * expect(foo).to.be.an.instanceof(Foo);
443 | *
444 | * @name a
445 | * @alias an
446 | * @param {String} type
447 | * @param {String} message _optional_
448 | * @namespace BDD
449 | * @api public
450 | */
451 |
452 | function an (type, msg) {
453 | if (msg) flag(this, 'message', msg);
454 | type = type.toLowerCase();
455 | var obj = flag(this, 'object')
456 | , article = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(type.charAt(0)) ? 'an ' : 'a ';
457 |
458 | this.assert(
459 | type === _.type(obj)
460 | , 'expected #{this} to be ' + article + type
461 | , 'expected #{this} not to be ' + article + type
462 | );
463 | }
464 |
465 | Assertion.addChainableMethod('an', an);
466 | Assertion.addChainableMethod('a', an);
467 |
468 | /**
469 | * ### .include(value)
470 | *
471 | * The `include` and `contain` assertions can be used as either property
472 | * based language chains or as methods to assert the inclusion of an object
473 | * in an array or a substring in a string. When used as language chains,
474 | * they toggle the `contains` flag for the `keys` assertion.
475 | *
476 | * expect([1,2,3]).to.include(2);
477 | * expect('foobar').to.contain('foo');
478 | * expect({ foo: 'bar', hello: 'universe' }).to.include.keys('foo');
479 | *
480 | * @name include
481 | * @alias contain
482 | * @alias includes
483 | * @alias contains
484 | * @param {Object|String|Number} obj
485 | * @param {String} message _optional_
486 | * @namespace BDD
487 | * @api public
488 | */
489 |
490 | function includeChainingBehavior () {
491 | flag(this, 'contains', true);
492 | }
493 |
494 | function include (val, msg) {
495 | _.expectTypes(this, ['array', 'object', 'string']);
496 |
497 | if (msg) flag(this, 'message', msg);
498 | var obj = flag(this, 'object');
499 | var expected = false;
500 |
501 | if (_.type(obj) === 'array' && _.type(val) === 'object') {
502 | for (var i in obj) {
503 | if (_.eql(obj[i], val)) {
504 | expected = true;
505 | break;
506 | }
507 | }
508 | } else if (_.type(val) === 'object') {
509 | if (!flag(this, 'negate')) {
510 | for (var k in val) new Assertion(obj).property(k, val[k]);
511 | return;
512 | }
513 | var subset = {};
514 | for (var k in val) subset[k] = obj[k];
515 | expected = _.eql(subset, val);
516 | } else {
517 | expected = (obj != undefined) && ~obj.indexOf(val);
518 | }
519 | this.assert(
520 | expected
521 | , 'expected #{this} to include ' + _.inspect(val)
522 | , 'expected #{this} to not include ' + _.inspect(val));
523 | }
524 |
525 | Assertion.addChainableMethod('include', include, includeChainingBehavior);
526 | Assertion.addChainableMethod('contain', include, includeChainingBehavior);
527 | Assertion.addChainableMethod('contains', include, includeChainingBehavior);
528 | Assertion.addChainableMethod('includes', include, includeChainingBehavior);
529 |
530 | /**
531 | * ### .ok
532 | *
533 | * Asserts that the target is truthy.
534 | *
535 | * expect('everything').to.be.ok;
536 | * expect(1).to.be.ok;
537 | * expect(false).to.not.be.ok;
538 | * expect(undefined).to.not.be.ok;
539 | * expect(null).to.not.be.ok;
540 | *
541 | * @name ok
542 | * @namespace BDD
543 | * @api public
544 | */
545 |
546 | Assertion.addProperty('ok', function () {
547 | this.assert(
548 | flag(this, 'object')
549 | , 'expected #{this} to be truthy'
550 | , 'expected #{this} to be falsy');
551 | });
552 |
553 | /**
554 | * ### .true
555 | *
556 | * Asserts that the target is `true`.
557 | *
558 | * expect(true).to.be.true;
559 | * expect(1).to.not.be.true;
560 | *
561 | * @name true
562 | * @namespace BDD
563 | * @api public
564 | */
565 |
566 | Assertion.addProperty('true', function () {
567 | this.assert(
568 | true === flag(this, 'object')
569 | , 'expected #{this} to be true'
570 | , 'expected #{this} to be false'
571 | , this.negate ? false : true
572 | );
573 | });
574 |
575 | /**
576 | * ### .false
577 | *
578 | * Asserts that the target is `false`.
579 | *
580 | * expect(false).to.be.false;
581 | * expect(0).to.not.be.false;
582 | *
583 | * @name false
584 | * @namespace BDD
585 | * @api public
586 | */
587 |
588 | Assertion.addProperty('false', function () {
589 | this.assert(
590 | false === flag(this, 'object')
591 | , 'expected #{this} to be false'
592 | , 'expected #{this} to be true'
593 | , this.negate ? true : false
594 | );
595 | });
596 |
597 | /**
598 | * ### .null
599 | *
600 | * Asserts that the target is `null`.
601 | *
602 | * expect(null).to.be.null;
603 | * expect(undefined).to.not.be.null;
604 | *
605 | * @name null
606 | * @namespace BDD
607 | * @api public
608 | */
609 |
610 | Assertion.addProperty('null', function () {
611 | this.assert(
612 | null === flag(this, 'object')
613 | , 'expected #{this} to be null'
614 | , 'expected #{this} not to be null'
615 | );
616 | });
617 |
618 | /**
619 | * ### .undefined
620 | *
621 | * Asserts that the target is `undefined`.
622 | *
623 | * expect(undefined).to.be.undefined;
624 | * expect(null).to.not.be.undefined;
625 | *
626 | * @name undefined
627 | * @namespace BDD
628 | * @api public
629 | */
630 |
631 | Assertion.addProperty('undefined', function () {
632 | this.assert(
633 | undefined === flag(this, 'object')
634 | , 'expected #{this} to be undefined'
635 | , 'expected #{this} not to be undefined'
636 | );
637 | });
638 |
639 | /**
640 | * ### .NaN
641 | * Asserts that the target is `NaN`.
642 | *
643 | * expect('foo').to.be.NaN;
644 | * expect(4).not.to.be.NaN;
645 | *
646 | * @name NaN
647 | * @namespace BDD
648 | * @api public
649 | */
650 |
651 | Assertion.addProperty('NaN', function () {
652 | this.assert(
653 | isNaN(flag(this, 'object'))
654 | , 'expected #{this} to be NaN'
655 | , 'expected #{this} not to be NaN'
656 | );
657 | });
658 |
659 | /**
660 | * ### .exist
661 | *
662 | * Asserts that the target is neither `null` nor `undefined`.
663 | *
664 | * var foo = 'hi'
665 | * , bar = null
666 | * , baz;
667 | *
668 | * expect(foo).to.exist;
669 | * expect(bar).to.not.exist;
670 | * expect(baz).to.not.exist;
671 | *
672 | * @name exist
673 | * @namespace BDD
674 | * @api public
675 | */
676 |
677 | Assertion.addProperty('exist', function () {
678 | this.assert(
679 | null != flag(this, 'object')
680 | , 'expected #{this} to exist'
681 | , 'expected #{this} to not exist'
682 | );
683 | });
684 |
685 |
686 | /**
687 | * ### .empty
688 | *
689 | * Asserts that the target's length is `0`. For arrays and strings, it checks
690 | * the `length` property. For objects, it gets the count of
691 | * enumerable keys.
692 | *
693 | * expect([]).to.be.empty;
694 | * expect('').to.be.empty;
695 | * expect({}).to.be.empty;
696 | *
697 | * @name empty
698 | * @namespace BDD
699 | * @api public
700 | */
701 |
702 | Assertion.addProperty('empty', function () {
703 | var obj = flag(this, 'object')
704 | , expected = obj;
705 |
706 | if (Array.isArray(obj) || 'string' === typeof object) {
707 | expected = obj.length;
708 | } else if (typeof obj === 'object') {
709 | expected = Object.keys(obj).length;
710 | }
711 |
712 | this.assert(
713 | !expected
714 | , 'expected #{this} to be empty'
715 | , 'expected #{this} not to be empty'
716 | );
717 | });
718 |
719 | /**
720 | * ### .arguments
721 | *
722 | * Asserts that the target is an arguments object.
723 | *
724 | * function test () {
725 | * expect(arguments).to.be.arguments;
726 | * }
727 | *
728 | * @name arguments
729 | * @alias Arguments
730 | * @namespace BDD
731 | * @api public
732 | */
733 |
734 | function checkArguments () {
735 | var obj = flag(this, 'object')
736 | , type = Object.prototype.toString.call(obj);
737 | this.assert(
738 | '[object Arguments]' === type
739 | , 'expected #{this} to be arguments but got ' + type
740 | , 'expected #{this} to not be arguments'
741 | );
742 | }
743 |
744 | Assertion.addProperty('arguments', checkArguments);
745 | Assertion.addProperty('Arguments', checkArguments);
746 |
747 | /**
748 | * ### .equal(value)
749 | *
750 | * Asserts that the target is strictly equal (`===`) to `value`.
751 | * Alternately, if the `deep` flag is set, asserts that
752 | * the target is deeply equal to `value`.
753 | *
754 | * expect('hello').to.equal('hello');
755 | * expect(42).to.equal(42);
756 | * expect(1).to.not.equal(true);
757 | * expect({ foo: 'bar' }).to.not.equal({ foo: 'bar' });
758 | * expect({ foo: 'bar' }).to.deep.equal({ foo: 'bar' });
759 | *
760 | * @name equal
761 | * @alias equals
762 | * @alias eq
763 | * @alias deep.equal
764 | * @param {Mixed} value
765 | * @param {String} message _optional_
766 | * @namespace BDD
767 | * @api public
768 | */
769 |
770 | function assertEqual (val, msg) {
771 | if (msg) flag(this, 'message', msg);
772 | var obj = flag(this, 'object');
773 | if (flag(this, 'deep')) {
774 | return this.eql(val);
775 | } else {
776 | this.assert(
777 | val === obj
778 | , 'expected #{this} to equal #{exp}'
779 | , 'expected #{this} to not equal #{exp}'
780 | , val
781 | , this._obj
782 | , true
783 | );
784 | }
785 | }
786 |
787 | Assertion.addMethod('equal', assertEqual);
788 | Assertion.addMethod('equals', assertEqual);
789 | Assertion.addMethod('eq', assertEqual);
790 |
791 | /**
792 | * ### .eql(value)
793 | *
794 | * Asserts that the target is deeply equal to `value`.
795 | *
796 | * expect({ foo: 'bar' }).to.eql({ foo: 'bar' });
797 | * expect([ 1, 2, 3 ]).to.eql([ 1, 2, 3 ]);
798 | *
799 | * @name eql
800 | * @alias eqls
801 | * @param {Mixed} value
802 | * @param {String} message _optional_
803 | * @namespace BDD
804 | * @api public
805 | */
806 |
807 | function assertEql(obj, msg) {
808 | if (msg) flag(this, 'message', msg);
809 | this.assert(
810 | _.eql(obj, flag(this, 'object'))
811 | , 'expected #{this} to deeply equal #{exp}'
812 | , 'expected #{this} to not deeply equal #{exp}'
813 | , obj
814 | , this._obj
815 | , true
816 | );
817 | }
818 |
819 | Assertion.addMethod('eql', assertEql);
820 | Assertion.addMethod('eqls', assertEql);
821 |
822 | /**
823 | * ### .above(value)
824 | *
825 | * Asserts that the target is greater than `value`.
826 | *
827 | * expect(10).to.be.above(5);
828 | *
829 | * Can also be used in conjunction with `length` to
830 | * assert a minimum length. The benefit being a
831 | * more informative error message than if the length
832 | * was supplied directly.
833 | *
834 | * expect('foo').to.have.length.above(2);
835 | * expect([ 1, 2, 3 ]).to.have.length.above(2);
836 | *
837 | * @name above
838 | * @alias gt
839 | * @alias greaterThan
840 | * @param {Number} value
841 | * @param {String} message _optional_
842 | * @namespace BDD
843 | * @api public
844 | */
845 |
846 | function assertAbove (n, msg) {
847 | if (msg) flag(this, 'message', msg);
848 | var obj = flag(this, 'object');
849 | if (flag(this, 'doLength')) {
850 | new Assertion(obj, msg).to.have.property('length');
851 | var len = obj.length;
852 | this.assert(
853 | len > n
854 | , 'expected #{this} to have a length above #{exp} but got #{act}'
855 | , 'expected #{this} to not have a length above #{exp}'
856 | , n
857 | , len
858 | );
859 | } else {
860 | this.assert(
861 | obj > n
862 | , 'expected #{this} to be above ' + n
863 | , 'expected #{this} to be at most ' + n
864 | );
865 | }
866 | }
867 |
868 | Assertion.addMethod('above', assertAbove);
869 | Assertion.addMethod('gt', assertAbove);
870 | Assertion.addMethod('greaterThan', assertAbove);
871 |
872 | /**
873 | * ### .least(value)
874 | *
875 | * Asserts that the target is greater than or equal to `value`.
876 | *
877 | * expect(10).to.be.at.least(10);
878 | *
879 | * Can also be used in conjunction with `length` to
880 | * assert a minimum length. The benefit being a
881 | * more informative error message than if the length
882 | * was supplied directly.
883 | *
884 | * expect('foo').to.have.length.of.at.least(2);
885 | * expect([ 1, 2, 3 ]).to.have.length.of.at.least(3);
886 | *
887 | * @name least
888 | * @alias gte
889 | * @param {Number} value
890 | * @param {String} message _optional_
891 | * @namespace BDD
892 | * @api public
893 | */
894 |
895 | function assertLeast (n, msg) {
896 | if (msg) flag(this, 'message', msg);
897 | var obj = flag(this, 'object');
898 | if (flag(this, 'doLength')) {
899 | new Assertion(obj, msg).to.have.property('length');
900 | var len = obj.length;
901 | this.assert(
902 | len >= n
903 | , 'expected #{this} to have a length at least #{exp} but got #{act}'
904 | , 'expected #{this} to have a length below #{exp}'
905 | , n
906 | , len
907 | );
908 | } else {
909 | this.assert(
910 | obj >= n
911 | , 'expected #{this} to be at least ' + n
912 | , 'expected #{this} to be below ' + n
913 | );
914 | }
915 | }
916 |
917 | Assertion.addMethod('least', assertLeast);
918 | Assertion.addMethod('gte', assertLeast);
919 |
920 | /**
921 | * ### .below(value)
922 | *
923 | * Asserts that the target is less than `value`.
924 | *
925 | * expect(5).to.be.below(10);
926 | *
927 | * Can also be used in conjunction with `length` to
928 | * assert a maximum length. The benefit being a
929 | * more informative error message than if the length
930 | * was supplied directly.
931 | *
932 | * expect('foo').to.have.length.below(4);
933 | * expect([ 1, 2, 3 ]).to.have.length.below(4);
934 | *
935 | * @name below
936 | * @alias lt
937 | * @alias lessThan
938 | * @param {Number} value
939 | * @param {String} message _optional_
940 | * @namespace BDD
941 | * @api public
942 | */
943 |
944 | function assertBelow (n, msg) {
945 | if (msg) flag(this, 'message', msg);
946 | var obj = flag(this, 'object');
947 | if (flag(this, 'doLength')) {
948 | new Assertion(obj, msg).to.have.property('length');
949 | var len = obj.length;
950 | this.assert(
951 | len < n
952 | , 'expected #{this} to have a length below #{exp} but got #{act}'
953 | , 'expected #{this} to not have a length below #{exp}'
954 | , n
955 | , len
956 | );
957 | } else {
958 | this.assert(
959 | obj < n
960 | , 'expected #{this} to be below ' + n
961 | , 'expected #{this} to be at least ' + n
962 | );
963 | }
964 | }
965 |
966 | Assertion.addMethod('below', assertBelow);
967 | Assertion.addMethod('lt', assertBelow);
968 | Assertion.addMethod('lessThan', assertBelow);
969 |
970 | /**
971 | * ### .most(value)
972 | *
973 | * Asserts that the target is less than or equal to `value`.
974 | *
975 | * expect(5).to.be.at.most(5);
976 | *
977 | * Can also be used in conjunction with `length` to
978 | * assert a maximum length. The benefit being a
979 | * more informative error message than if the length
980 | * was supplied directly.
981 | *
982 | * expect('foo').to.have.length.of.at.most(4);
983 | * expect([ 1, 2, 3 ]).to.have.length.of.at.most(3);
984 | *
985 | * @name most
986 | * @alias lte
987 | * @param {Number} value
988 | * @param {String} message _optional_
989 | * @namespace BDD
990 | * @api public
991 | */
992 |
993 | function assertMost (n, msg) {
994 | if (msg) flag(this, 'message', msg);
995 | var obj = flag(this, 'object');
996 | if (flag(this, 'doLength')) {
997 | new Assertion(obj, msg).to.have.property('length');
998 | var len = obj.length;
999 | this.assert(
1000 | len <= n
1001 | , 'expected #{this} to have a length at most #{exp} but got #{act}'
1002 | , 'expected #{this} to have a length above #{exp}'
1003 | , n
1004 | , len
1005 | );
1006 | } else {
1007 | this.assert(
1008 | obj <= n
1009 | , 'expected #{this} to be at most ' + n
1010 | , 'expected #{this} to be above ' + n
1011 | );
1012 | }
1013 | }
1014 |
1015 | Assertion.addMethod('most', assertMost);
1016 | Assertion.addMethod('lte', assertMost);
1017 |
1018 | /**
1019 | * ### .within(start, finish)
1020 | *
1021 | * Asserts that the target is within a range.
1022 | *
1023 | * expect(7).to.be.within(5,10);
1024 | *
1025 | * Can also be used in conjunction with `length` to
1026 | * assert a length range. The benefit being a
1027 | * more informative error message than if the length
1028 | * was supplied directly.
1029 | *
1030 | * expect('foo').to.have.length.within(2,4);
1031 | * expect([ 1, 2, 3 ]).to.have.length.within(2,4);
1032 | *
1033 | * @name within
1034 | * @param {Number} start lowerbound inclusive
1035 | * @param {Number} finish upperbound inclusive
1036 | * @param {String} message _optional_
1037 | * @namespace BDD
1038 | * @api public
1039 | */
1040 |
1041 | Assertion.addMethod('within', function (start, finish, msg) {
1042 | if (msg) flag(this, 'message', msg);
1043 | var obj = flag(this, 'object')
1044 | , range = start + '..' + finish;
1045 | if (flag(this, 'doLength')) {
1046 | new Assertion(obj, msg).to.have.property('length');
1047 | var len = obj.length;
1048 | this.assert(
1049 | len >= start && len <= finish
1050 | , 'expected #{this} to have a length within ' + range
1051 | , 'expected #{this} to not have a length within ' + range
1052 | );
1053 | } else {
1054 | this.assert(
1055 | obj >= start && obj <= finish
1056 | , 'expected #{this} to be within ' + range
1057 | , 'expected #{this} to not be within ' + range
1058 | );
1059 | }
1060 | });
1061 |
1062 | /**
1063 | * ### .instanceof(constructor)
1064 | *
1065 | * Asserts that the target is an instance of `constructor`.
1066 | *
1067 | * var Tea = function (name) { this.name = name; }
1068 | * , Chai = new Tea('chai');
1069 | *
1070 | * expect(Chai).to.be.an.instanceof(Tea);
1071 | * expect([ 1, 2, 3 ]).to.be.instanceof(Array);
1072 | *
1073 | * @name instanceof
1074 | * @param {Constructor} constructor
1075 | * @param {String} message _optional_
1076 | * @alias instanceOf
1077 | * @namespace BDD
1078 | * @api public
1079 | */
1080 |
1081 | function assertInstanceOf (constructor, msg) {
1082 | if (msg) flag(this, 'message', msg);
1083 | var name = _.getName(constructor);
1084 | this.assert(
1085 | flag(this, 'object') instanceof constructor
1086 | , 'expected #{this} to be an instance of ' + name
1087 | , 'expected #{this} to not be an instance of ' + name
1088 | );
1089 | };
1090 |
1091 | Assertion.addMethod('instanceof', assertInstanceOf);
1092 | Assertion.addMethod('instanceOf', assertInstanceOf);
1093 |
1094 | /**
1095 | * ### .property(name, [value])
1096 | *
1097 | * Asserts that the target has a property `name`, optionally asserting that
1098 | * the value of that property is strictly equal to `value`.
1099 | * If the `deep` flag is set, you can use dot- and bracket-notation for deep
1100 | * references into objects and arrays.
1101 | *
1102 | * // simple referencing
1103 | * var obj = { foo: 'bar' };
1104 | * expect(obj).to.have.property('foo');
1105 | * expect(obj).to.have.property('foo', 'bar');
1106 | *
1107 | * // deep referencing
1108 | * var deepObj = {
1109 | * green: { tea: 'matcha' }
1110 | * , teas: [ 'chai', 'matcha', { tea: 'konacha' } ]
1111 | * };
1112 | *
1113 | * expect(deepObj).to.have.deep.property('green.tea', 'matcha');
1114 | * expect(deepObj).to.have.deep.property('teas[1]', 'matcha');
1115 | * expect(deepObj).to.have.deep.property('teas[2].tea', 'konacha');
1116 | *
1117 | * You can also use an array as the starting point of a `deep.property`
1118 | * assertion, or traverse nested arrays.
1119 | *
1120 | * var arr = [
1121 | * [ 'chai', 'matcha', 'konacha' ]
1122 | * , [ { tea: 'chai' }
1123 | * , { tea: 'matcha' }
1124 | * , { tea: 'konacha' } ]
1125 | * ];
1126 | *
1127 | * expect(arr).to.have.deep.property('[0][1]', 'matcha');
1128 | * expect(arr).to.have.deep.property('[1][2].tea', 'konacha');
1129 | *
1130 | * Furthermore, `property` changes the subject of the assertion
1131 | * to be the value of that property from the original object. This
1132 | * permits for further chainable assertions on that property.
1133 | *
1134 | * expect(obj).to.have.property('foo')
1135 | * .that.is.a('string');
1136 | * expect(deepObj).to.have.property('green')
1137 | * .that.is.an('object')
1138 | * .that.deep.equals({ tea: 'matcha' });
1139 | * expect(deepObj).to.have.property('teas')
1140 | * .that.is.an('array')
1141 | * .with.deep.property('[2]')
1142 | * .that.deep.equals({ tea: 'konacha' });
1143 | *
1144 | * Note that dots and bracket in `name` must be backslash-escaped when
1145 | * the `deep` flag is set, while they must NOT be escaped when the `deep`
1146 | * flag is not set.
1147 | *
1148 | * // simple referencing
1149 | * var css = { '.link[target]': 42 };
1150 | * expect(css).to.have.property('.link[target]', 42);
1151 | *
1152 | * // deep referencing
1153 | * var deepCss = { '.link': { '[target]': 42 }};
1154 | * expect(deepCss).to.have.deep.property('\\.link.\\[target\\]', 42);
1155 | *
1156 | * @name property
1157 | * @alias deep.property
1158 | * @param {String} name
1159 | * @param {Mixed} value (optional)
1160 | * @param {String} message _optional_
1161 | * @returns value of property for chaining
1162 | * @namespace BDD
1163 | * @api public
1164 | */
1165 |
1166 | Assertion.addMethod('property', function (name, val, msg) {
1167 | if (msg) flag(this, 'message', msg);
1168 |
1169 | var isDeep = !!flag(this, 'deep')
1170 | , descriptor = isDeep ? 'deep property ' : 'property '
1171 | , negate = flag(this, 'negate')
1172 | , obj = flag(this, 'object')
1173 | , pathInfo = isDeep ? _.getPathInfo(name, obj) : null
1174 | , hasProperty = isDeep
1175 | ? pathInfo.exists
1176 | : _.hasProperty(name, obj)
1177 | , value = isDeep
1178 | ? pathInfo.value
1179 | : obj[name];
1180 |
1181 | if (negate && arguments.length > 1) {
1182 | if (undefined === value) {
1183 | msg = (msg != null) ? msg + ': ' : '';
1184 | throw new Error(msg + _.inspect(obj) + ' has no ' + descriptor + _.inspect(name));
1185 | }
1186 | } else {
1187 | this.assert(
1188 | hasProperty
1189 | , 'expected #{this} to have a ' + descriptor + _.inspect(name)
1190 | , 'expected #{this} to not have ' + descriptor + _.inspect(name));
1191 | }
1192 |
1193 | if (arguments.length > 1) {
1194 | this.assert(
1195 | val === value
1196 | , 'expected #{this} to have a ' + descriptor + _.inspect(name) + ' of #{exp}, but got #{act}'
1197 | , 'expected #{this} to not have a ' + descriptor + _.inspect(name) + ' of #{act}'
1198 | , val
1199 | , value
1200 | );
1201 | }
1202 |
1203 | flag(this, 'object', value);
1204 | });
1205 |
1206 |
1207 | /**
1208 | * ### .ownProperty(name)
1209 | *
1210 | * Asserts that the target has an own property `name`.
1211 | *
1212 | * expect('test').to.have.ownProperty('length');
1213 | *
1214 | * @name ownProperty
1215 | * @alias haveOwnProperty
1216 | * @param {String} name
1217 | * @param {String} message _optional_
1218 | * @namespace BDD
1219 | * @api public
1220 | */
1221 |
1222 | function assertOwnProperty (name, msg) {
1223 | if (msg) flag(this, 'message', msg);
1224 | var obj = flag(this, 'object');
1225 | this.assert(
1226 | obj.hasOwnProperty(name)
1227 | , 'expected #{this} to have own property ' + _.inspect(name)
1228 | , 'expected #{this} to not have own property ' + _.inspect(name)
1229 | );
1230 | }
1231 |
1232 | Assertion.addMethod('ownProperty', assertOwnProperty);
1233 | Assertion.addMethod('haveOwnProperty', assertOwnProperty);
1234 |
1235 | /**
1236 | * ### .ownPropertyDescriptor(name[, descriptor[, message]])
1237 | *
1238 | * Asserts that the target has an own property descriptor `name`, that optionally matches `descriptor`.
1239 | *
1240 | * expect('test').to.have.ownPropertyDescriptor('length');
1241 | * expect('test').to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 4 });
1242 | * expect('test').not.to.have.ownPropertyDescriptor('length', { enumerable: false, configurable: false, writable: false, value: 3 });
1243 | * expect('test').ownPropertyDescriptor('length').to.have.property('enumerable', false);
1244 | * expect('test').ownPropertyDescriptor('length').to.have.keys('value');
1245 | *
1246 | * @name ownPropertyDescriptor
1247 | * @alias haveOwnPropertyDescriptor
1248 | * @param {String} name
1249 | * @param {Object} descriptor _optional_
1250 | * @param {String} message _optional_
1251 | * @namespace BDD
1252 | * @api public
1253 | */
1254 |
1255 | function assertOwnPropertyDescriptor (name, descriptor, msg) {
1256 | if (typeof descriptor === 'string') {
1257 | msg = descriptor;
1258 | descriptor = null;
1259 | }
1260 | if (msg) flag(this, 'message', msg);
1261 | var obj = flag(this, 'object');
1262 | var actualDescriptor = Object.getOwnPropertyDescriptor(Object(obj), name);
1263 | if (actualDescriptor && descriptor) {
1264 | this.assert(
1265 | _.eql(descriptor, actualDescriptor)
1266 | , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to match ' + _.inspect(descriptor) + ', got ' + _.inspect(actualDescriptor)
1267 | , 'expected the own property descriptor for ' + _.inspect(name) + ' on #{this} to not match ' + _.inspect(descriptor)
1268 | , descriptor
1269 | , actualDescriptor
1270 | , true
1271 | );
1272 | } else {
1273 | this.assert(
1274 | actualDescriptor
1275 | , 'expected #{this} to have an own property descriptor for ' + _.inspect(name)
1276 | , 'expected #{this} to not have an own property descriptor for ' + _.inspect(name)
1277 | );
1278 | }
1279 | flag(this, 'object', actualDescriptor);
1280 | }
1281 |
1282 | Assertion.addMethod('ownPropertyDescriptor', assertOwnPropertyDescriptor);
1283 | Assertion.addMethod('haveOwnPropertyDescriptor', assertOwnPropertyDescriptor);
1284 |
1285 | /**
1286 | * ### .length
1287 | *
1288 | * Sets the `doLength` flag later used as a chain precursor to a value
1289 | * comparison for the `length` property.
1290 | *
1291 | * expect('foo').to.have.length.above(2);
1292 | * expect([ 1, 2, 3 ]).to.have.length.above(2);
1293 | * expect('foo').to.have.length.below(4);
1294 | * expect([ 1, 2, 3 ]).to.have.length.below(4);
1295 | * expect('foo').to.have.length.within(2,4);
1296 | * expect([ 1, 2, 3 ]).to.have.length.within(2,4);
1297 | *
1298 | * *Deprecation notice:* Using `length` as an assertion will be deprecated
1299 | * in version 2.4.0 and removed in 3.0.0. Code using the old style of
1300 | * asserting for `length` property value using `length(value)` should be
1301 | * switched to use `lengthOf(value)` instead.
1302 | *
1303 | * @name length
1304 | * @namespace BDD
1305 | * @api public
1306 | */
1307 |
1308 | /**
1309 | * ### .lengthOf(value[, message])
1310 | *
1311 | * Asserts that the target's `length` property has
1312 | * the expected value.
1313 | *
1314 | * expect([ 1, 2, 3]).to.have.lengthOf(3);
1315 | * expect('foobar').to.have.lengthOf(6);
1316 | *
1317 | * @name lengthOf
1318 | * @param {Number} length
1319 | * @param {String} message _optional_
1320 | * @namespace BDD
1321 | * @api public
1322 | */
1323 |
1324 | function assertLengthChain () {
1325 | flag(this, 'doLength', true);
1326 | }
1327 |
1328 | function assertLength (n, msg) {
1329 | if (msg) flag(this, 'message', msg);
1330 | var obj = flag(this, 'object');
1331 | new Assertion(obj, msg).to.have.property('length');
1332 | var len = obj.length;
1333 |
1334 | this.assert(
1335 | len == n
1336 | , 'expected #{this} to have a length of #{exp} but got #{act}'
1337 | , 'expected #{this} to not have a length of #{act}'
1338 | , n
1339 | , len
1340 | );
1341 | }
1342 |
1343 | Assertion.addChainableMethod('length', assertLength, assertLengthChain);
1344 | Assertion.addMethod('lengthOf', assertLength);
1345 |
1346 | /**
1347 | * ### .match(regexp)
1348 | *
1349 | * Asserts that the target matches a regular expression.
1350 | *
1351 | * expect('foobar').to.match(/^foo/);
1352 | *
1353 | * @name match
1354 | * @alias matches
1355 | * @param {RegExp} RegularExpression
1356 | * @param {String} message _optional_
1357 | * @namespace BDD
1358 | * @api public
1359 | */
1360 | function assertMatch(re, msg) {
1361 | if (msg) flag(this, 'message', msg);
1362 | var obj = flag(this, 'object');
1363 | this.assert(
1364 | re.exec(obj)
1365 | , 'expected #{this} to match ' + re
1366 | , 'expected #{this} not to match ' + re
1367 | );
1368 | }
1369 |
1370 | Assertion.addMethod('match', assertMatch);
1371 | Assertion.addMethod('matches', assertMatch);
1372 |
1373 | /**
1374 | * ### .string(string)
1375 | *
1376 | * Asserts that the string target contains another string.
1377 | *
1378 | * expect('foobar').to.have.string('bar');
1379 | *
1380 | * @name string
1381 | * @param {String} string
1382 | * @param {String} message _optional_
1383 | * @namespace BDD
1384 | * @api public
1385 | */
1386 |
1387 | Assertion.addMethod('string', function (str, msg) {
1388 | if (msg) flag(this, 'message', msg);
1389 | var obj = flag(this, 'object');
1390 | new Assertion(obj, msg).is.a('string');
1391 |
1392 | this.assert(
1393 | ~obj.indexOf(str)
1394 | , 'expected #{this} to contain ' + _.inspect(str)
1395 | , 'expected #{this} to not contain ' + _.inspect(str)
1396 | );
1397 | });
1398 |
1399 |
1400 | /**
1401 | * ### .keys(key1, [key2], [...])
1402 | *
1403 | * Asserts that the target contains any or all of the passed-in keys.
1404 | * Use in combination with `any`, `all`, `contains`, or `have` will affect
1405 | * what will pass.
1406 | *
1407 | * When used in conjunction with `any`, at least one key that is passed
1408 | * in must exist in the target object. This is regardless whether or not
1409 | * the `have` or `contain` qualifiers are used. Note, either `any` or `all`
1410 | * should be used in the assertion. If neither are used, the assertion is
1411 | * defaulted to `all`.
1412 | *
1413 | * When both `all` and `contain` are used, the target object must have at
1414 | * least all of the passed-in keys but may have more keys not listed.
1415 | *
1416 | * When both `all` and `have` are used, the target object must both contain
1417 | * all of the passed-in keys AND the number of keys in the target object must
1418 | * match the number of keys passed in (in other words, a target object must
1419 | * have all and only all of the passed-in keys).
1420 | *
1421 | * expect({ foo: 1, bar: 2 }).to.have.any.keys('foo', 'baz');
1422 | * expect({ foo: 1, bar: 2 }).to.have.any.keys('foo');
1423 | * expect({ foo: 1, bar: 2 }).to.contain.any.keys('bar', 'baz');
1424 | * expect({ foo: 1, bar: 2 }).to.contain.any.keys(['foo']);
1425 | * expect({ foo: 1, bar: 2 }).to.contain.any.keys({'foo': 6});
1426 | * expect({ foo: 1, bar: 2 }).to.have.all.keys(['bar', 'foo']);
1427 | * expect({ foo: 1, bar: 2 }).to.have.all.keys({'bar': 6, 'foo': 7});
1428 | * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys(['bar', 'foo']);
1429 | * expect({ foo: 1, bar: 2, baz: 3 }).to.contain.all.keys({'bar': 6});
1430 | *
1431 | *
1432 | * @name keys
1433 | * @alias key
1434 | * @param {...String|Array|Object} keys
1435 | * @namespace BDD
1436 | * @api public
1437 | */
1438 |
1439 | function assertKeys (keys) {
1440 | var obj = flag(this, 'object')
1441 | , str
1442 | , ok = true
1443 | , mixedArgsMsg = 'keys must be given single argument of Array|Object|String, or multiple String arguments';
1444 |
1445 | switch (_.type(keys)) {
1446 | case "array":
1447 | if (arguments.length > 1) throw (new Error(mixedArgsMsg));
1448 | break;
1449 | case "object":
1450 | if (arguments.length > 1) throw (new Error(mixedArgsMsg));
1451 | keys = Object.keys(keys);
1452 | break;
1453 | default:
1454 | keys = Array.prototype.slice.call(arguments);
1455 | }
1456 |
1457 | if (!keys.length) throw new Error('keys required');
1458 |
1459 | var actual = Object.keys(obj)
1460 | , expected = keys
1461 | , len = keys.length
1462 | , any = flag(this, 'any')
1463 | , all = flag(this, 'all');
1464 |
1465 | if (!any && !all) {
1466 | all = true;
1467 | }
1468 |
1469 | // Has any
1470 | if (any) {
1471 | var intersection = expected.filter(function(key) {
1472 | return ~actual.indexOf(key);
1473 | });
1474 | ok = intersection.length > 0;
1475 | }
1476 |
1477 | // Has all
1478 | if (all) {
1479 | ok = keys.every(function(key){
1480 | return ~actual.indexOf(key);
1481 | });
1482 | if (!flag(this, 'negate') && !flag(this, 'contains')) {
1483 | ok = ok && keys.length == actual.length;
1484 | }
1485 | }
1486 |
1487 | // Key string
1488 | if (len > 1) {
1489 | keys = keys.map(function(key){
1490 | return _.inspect(key);
1491 | });
1492 | var last = keys.pop();
1493 | if (all) {
1494 | str = keys.join(', ') + ', and ' + last;
1495 | }
1496 | if (any) {
1497 | str = keys.join(', ') + ', or ' + last;
1498 | }
1499 | } else {
1500 | str = _.inspect(keys[0]);
1501 | }
1502 |
1503 | // Form
1504 | str = (len > 1 ? 'keys ' : 'key ') + str;
1505 |
1506 | // Have / include
1507 | str = (flag(this, 'contains') ? 'contain ' : 'have ') + str;
1508 |
1509 | // Assertion
1510 | this.assert(
1511 | ok
1512 | , 'expected #{this} to ' + str
1513 | , 'expected #{this} to not ' + str
1514 | , expected.slice(0).sort()
1515 | , actual.sort()
1516 | , true
1517 | );
1518 | }
1519 |
1520 | Assertion.addMethod('keys', assertKeys);
1521 | Assertion.addMethod('key', assertKeys);
1522 |
1523 | /**
1524 | * ### .throw(constructor)
1525 | *
1526 | * Asserts that the function target will throw a specific error, or specific type of error
1527 | * (as determined using `instanceof`), optionally with a RegExp or string inclusion test
1528 | * for the error's message.
1529 | *
1530 | * var err = new ReferenceError('This is a bad function.');
1531 | * var fn = function () { throw err; }
1532 | * expect(fn).to.throw(ReferenceError);
1533 | * expect(fn).to.throw(Error);
1534 | * expect(fn).to.throw(/bad function/);
1535 | * expect(fn).to.not.throw('good function');
1536 | * expect(fn).to.throw(ReferenceError, /bad function/);
1537 | * expect(fn).to.throw(err);
1538 | *
1539 | * Please note that when a throw expectation is negated, it will check each
1540 | * parameter independently, starting with error constructor type. The appropriate way
1541 | * to check for the existence of a type of error but for a message that does not match
1542 | * is to use `and`.
1543 | *
1544 | * expect(fn).to.throw(ReferenceError)
1545 | * .and.not.throw(/good function/);
1546 | *
1547 | * @name throw
1548 | * @alias throws
1549 | * @alias Throw
1550 | * @param {ErrorConstructor} constructor
1551 | * @param {String|RegExp} expected error message
1552 | * @param {String} message _optional_
1553 | * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
1554 | * @returns error for chaining (null if no error)
1555 | * @namespace BDD
1556 | * @api public
1557 | */
1558 |
1559 | function assertThrows (constructor, errMsg, msg) {
1560 | if (msg) flag(this, 'message', msg);
1561 | var obj = flag(this, 'object');
1562 | new Assertion(obj, msg).is.a('function');
1563 |
1564 | var thrown = false
1565 | , desiredError = null
1566 | , name = null
1567 | , thrownError = null;
1568 |
1569 | if (arguments.length === 0) {
1570 | errMsg = null;
1571 | constructor = null;
1572 | } else if (constructor && (constructor instanceof RegExp || 'string' === typeof constructor)) {
1573 | errMsg = constructor;
1574 | constructor = null;
1575 | } else if (constructor && constructor instanceof Error) {
1576 | desiredError = constructor;
1577 | constructor = null;
1578 | errMsg = null;
1579 | } else if (typeof constructor === 'function') {
1580 | name = constructor.prototype.name;
1581 | if (!name || (name === 'Error' && constructor !== Error)) {
1582 | name = constructor.name || (new constructor()).name;
1583 | }
1584 | } else {
1585 | constructor = null;
1586 | }
1587 |
1588 | try {
1589 | obj();
1590 | } catch (err) {
1591 | // first, check desired error
1592 | if (desiredError) {
1593 | this.assert(
1594 | err === desiredError
1595 | , 'expected #{this} to throw #{exp} but #{act} was thrown'
1596 | , 'expected #{this} to not throw #{exp}'
1597 | , (desiredError instanceof Error ? desiredError.toString() : desiredError)
1598 | , (err instanceof Error ? err.toString() : err)
1599 | );
1600 |
1601 | flag(this, 'object', err);
1602 | return this;
1603 | }
1604 |
1605 | // next, check constructor
1606 | if (constructor) {
1607 | this.assert(
1608 | err instanceof constructor
1609 | , 'expected #{this} to throw #{exp} but #{act} was thrown'
1610 | , 'expected #{this} to not throw #{exp} but #{act} was thrown'
1611 | , name
1612 | , (err instanceof Error ? err.toString() : err)
1613 | );
1614 |
1615 | if (!errMsg) {
1616 | flag(this, 'object', err);
1617 | return this;
1618 | }
1619 | }
1620 |
1621 | // next, check message
1622 | var message = 'error' === _.type(err) && "message" in err
1623 | ? err.message
1624 | : '' + err;
1625 |
1626 | if ((message != null) && errMsg && errMsg instanceof RegExp) {
1627 | this.assert(
1628 | errMsg.exec(message)
1629 | , 'expected #{this} to throw error matching #{exp} but got #{act}'
1630 | , 'expected #{this} to throw error not matching #{exp}'
1631 | , errMsg
1632 | , message
1633 | );
1634 |
1635 | flag(this, 'object', err);
1636 | return this;
1637 | } else if ((message != null) && errMsg && 'string' === typeof errMsg) {
1638 | this.assert(
1639 | ~message.indexOf(errMsg)
1640 | , 'expected #{this} to throw error including #{exp} but got #{act}'
1641 | , 'expected #{this} to throw error not including #{act}'
1642 | , errMsg
1643 | , message
1644 | );
1645 |
1646 | flag(this, 'object', err);
1647 | return this;
1648 | } else {
1649 | thrown = true;
1650 | thrownError = err;
1651 | }
1652 | }
1653 |
1654 | var actuallyGot = ''
1655 | , expectedThrown = name !== null
1656 | ? name
1657 | : desiredError
1658 | ? '#{exp}' //_.inspect(desiredError)
1659 | : 'an error';
1660 |
1661 | if (thrown) {
1662 | actuallyGot = ' but #{act} was thrown'
1663 | }
1664 |
1665 | this.assert(
1666 | thrown === true
1667 | , 'expected #{this} to throw ' + expectedThrown + actuallyGot
1668 | , 'expected #{this} to not throw ' + expectedThrown + actuallyGot
1669 | , (desiredError instanceof Error ? desiredError.toString() : desiredError)
1670 | , (thrownError instanceof Error ? thrownError.toString() : thrownError)
1671 | );
1672 |
1673 | flag(this, 'object', thrownError);
1674 | };
1675 |
1676 | Assertion.addMethod('throw', assertThrows);
1677 | Assertion.addMethod('throws', assertThrows);
1678 | Assertion.addMethod('Throw', assertThrows);
1679 |
1680 | /**
1681 | * ### .respondTo(method)
1682 | *
1683 | * Asserts that the object or class target will respond to a method.
1684 | *
1685 | * Klass.prototype.bar = function(){};
1686 | * expect(Klass).to.respondTo('bar');
1687 | * expect(obj).to.respondTo('bar');
1688 | *
1689 | * To check if a constructor will respond to a static function,
1690 | * set the `itself` flag.
1691 | *
1692 | * Klass.baz = function(){};
1693 | * expect(Klass).itself.to.respondTo('baz');
1694 | *
1695 | * @name respondTo
1696 | * @alias respondsTo
1697 | * @param {String} method
1698 | * @param {String} message _optional_
1699 | * @namespace BDD
1700 | * @api public
1701 | */
1702 |
1703 | function respondTo (method, msg) {
1704 | if (msg) flag(this, 'message', msg);
1705 | var obj = flag(this, 'object')
1706 | , itself = flag(this, 'itself')
1707 | , context = ('function' === _.type(obj) && !itself)
1708 | ? obj.prototype[method]
1709 | : obj[method];
1710 |
1711 | this.assert(
1712 | 'function' === typeof context
1713 | , 'expected #{this} to respond to ' + _.inspect(method)
1714 | , 'expected #{this} to not respond to ' + _.inspect(method)
1715 | );
1716 | }
1717 |
1718 | Assertion.addMethod('respondTo', respondTo);
1719 | Assertion.addMethod('respondsTo', respondTo);
1720 |
1721 | /**
1722 | * ### .itself
1723 | *
1724 | * Sets the `itself` flag, later used by the `respondTo` assertion.
1725 | *
1726 | * function Foo() {}
1727 | * Foo.bar = function() {}
1728 | * Foo.prototype.baz = function() {}
1729 | *
1730 | * expect(Foo).itself.to.respondTo('bar');
1731 | * expect(Foo).itself.not.to.respondTo('baz');
1732 | *
1733 | * @name itself
1734 | * @namespace BDD
1735 | * @api public
1736 | */
1737 |
1738 | Assertion.addProperty('itself', function () {
1739 | flag(this, 'itself', true);
1740 | });
1741 |
1742 | /**
1743 | * ### .satisfy(method)
1744 | *
1745 | * Asserts that the target passes a given truth test.
1746 | *
1747 | * expect(1).to.satisfy(function(num) { return num > 0; });
1748 | *
1749 | * @name satisfy
1750 | * @alias satisfies
1751 | * @param {Function} matcher
1752 | * @param {String} message _optional_
1753 | * @namespace BDD
1754 | * @api public
1755 | */
1756 |
1757 | function satisfy (matcher, msg) {
1758 | if (msg) flag(this, 'message', msg);
1759 | var obj = flag(this, 'object');
1760 | var result = matcher(obj);
1761 | this.assert(
1762 | result
1763 | , 'expected #{this} to satisfy ' + _.objDisplay(matcher)
1764 | , 'expected #{this} to not satisfy' + _.objDisplay(matcher)
1765 | , this.negate ? false : true
1766 | , result
1767 | );
1768 | }
1769 |
1770 | Assertion.addMethod('satisfy', satisfy);
1771 | Assertion.addMethod('satisfies', satisfy);
1772 |
1773 | /**
1774 | * ### .closeTo(expected, delta)
1775 | *
1776 | * Asserts that the target is equal `expected`, to within a +/- `delta` range.
1777 | *
1778 | * expect(1.5).to.be.closeTo(1, 0.5);
1779 | *
1780 | * @name closeTo
1781 | * @alias approximately
1782 | * @param {Number} expected
1783 | * @param {Number} delta
1784 | * @param {String} message _optional_
1785 | * @namespace BDD
1786 | * @api public
1787 | */
1788 |
1789 | function closeTo(expected, delta, msg) {
1790 | if (msg) flag(this, 'message', msg);
1791 | var obj = flag(this, 'object');
1792 |
1793 | new Assertion(obj, msg).is.a('number');
1794 | if (_.type(expected) !== 'number' || _.type(delta) !== 'number') {
1795 | throw new Error('the arguments to closeTo or approximately must be numbers');
1796 | }
1797 |
1798 | this.assert(
1799 | Math.abs(obj - expected) <= delta
1800 | , 'expected #{this} to be close to ' + expected + ' +/- ' + delta
1801 | , 'expected #{this} not to be close to ' + expected + ' +/- ' + delta
1802 | );
1803 | }
1804 |
1805 | Assertion.addMethod('closeTo', closeTo);
1806 | Assertion.addMethod('approximately', closeTo);
1807 |
1808 | function isSubsetOf(subset, superset, cmp) {
1809 | return subset.every(function(elem) {
1810 | if (!cmp) return superset.indexOf(elem) !== -1;
1811 |
1812 | return superset.some(function(elem2) {
1813 | return cmp(elem, elem2);
1814 | });
1815 | })
1816 | }
1817 |
1818 | /**
1819 | * ### .members(set)
1820 | *
1821 | * Asserts that the target is a superset of `set`,
1822 | * or that the target and `set` have the same strictly-equal (===) members.
1823 | * Alternately, if the `deep` flag is set, set members are compared for deep
1824 | * equality.
1825 | *
1826 | * expect([1, 2, 3]).to.include.members([3, 2]);
1827 | * expect([1, 2, 3]).to.not.include.members([3, 2, 8]);
1828 | *
1829 | * expect([4, 2]).to.have.members([2, 4]);
1830 | * expect([5, 2]).to.not.have.members([5, 2, 1]);
1831 | *
1832 | * expect([{ id: 1 }]).to.deep.include.members([{ id: 1 }]);
1833 | *
1834 | * @name members
1835 | * @param {Array} set
1836 | * @param {String} message _optional_
1837 | * @namespace BDD
1838 | * @api public
1839 | */
1840 |
1841 | Assertion.addMethod('members', function (subset, msg) {
1842 | if (msg) flag(this, 'message', msg);
1843 | var obj = flag(this, 'object');
1844 |
1845 | new Assertion(obj).to.be.an('array');
1846 | new Assertion(subset).to.be.an('array');
1847 |
1848 | var cmp = flag(this, 'deep') ? _.eql : undefined;
1849 |
1850 | if (flag(this, 'contains')) {
1851 | return this.assert(
1852 | isSubsetOf(subset, obj, cmp)
1853 | , 'expected #{this} to be a superset of #{act}'
1854 | , 'expected #{this} to not be a superset of #{act}'
1855 | , obj
1856 | , subset
1857 | );
1858 | }
1859 |
1860 | this.assert(
1861 | isSubsetOf(obj, subset, cmp) && isSubsetOf(subset, obj, cmp)
1862 | , 'expected #{this} to have the same members as #{act}'
1863 | , 'expected #{this} to not have the same members as #{act}'
1864 | , obj
1865 | , subset
1866 | );
1867 | });
1868 |
1869 | /**
1870 | * ### .oneOf(list)
1871 | *
1872 | * Assert that a value appears somewhere in the top level of array `list`.
1873 | *
1874 | * expect('a').to.be.oneOf(['a', 'b', 'c']);
1875 | * expect(9).to.not.be.oneOf(['z']);
1876 | * expect([3]).to.not.be.oneOf([1, 2, [3]]);
1877 | *
1878 | * var three = [3];
1879 | * // for object-types, contents are not compared
1880 | * expect(three).to.not.be.oneOf([1, 2, [3]]);
1881 | * // comparing references works
1882 | * expect(three).to.be.oneOf([1, 2, three]);
1883 | *
1884 | * @name oneOf
1885 | * @param {Array<*>} list
1886 | * @param {String} message _optional_
1887 | * @namespace BDD
1888 | * @api public
1889 | */
1890 |
1891 | function oneOf (list, msg) {
1892 | if (msg) flag(this, 'message', msg);
1893 | var expected = flag(this, 'object');
1894 | new Assertion(list).to.be.an('array');
1895 |
1896 | this.assert(
1897 | list.indexOf(expected) > -1
1898 | , 'expected #{this} to be one of #{exp}'
1899 | , 'expected #{this} to not be one of #{exp}'
1900 | , list
1901 | , expected
1902 | );
1903 | }
1904 |
1905 | Assertion.addMethod('oneOf', oneOf);
1906 |
1907 |
1908 | /**
1909 | * ### .change(function)
1910 | *
1911 | * Asserts that a function changes an object property
1912 | *
1913 | * var obj = { val: 10 };
1914 | * var fn = function() { obj.val += 3 };
1915 | * var noChangeFn = function() { return 'foo' + 'bar'; }
1916 | * expect(fn).to.change(obj, 'val');
1917 | * expect(noChangeFn).to.not.change(obj, 'val')
1918 | *
1919 | * @name change
1920 | * @alias changes
1921 | * @alias Change
1922 | * @param {String} object
1923 | * @param {String} property name
1924 | * @param {String} message _optional_
1925 | * @namespace BDD
1926 | * @api public
1927 | */
1928 |
1929 | function assertChanges (object, prop, msg) {
1930 | if (msg) flag(this, 'message', msg);
1931 | var fn = flag(this, 'object');
1932 | new Assertion(object, msg).to.have.property(prop);
1933 | new Assertion(fn).is.a('function');
1934 |
1935 | var initial = object[prop];
1936 | fn();
1937 |
1938 | this.assert(
1939 | initial !== object[prop]
1940 | , 'expected .' + prop + ' to change'
1941 | , 'expected .' + prop + ' to not change'
1942 | );
1943 | }
1944 |
1945 | Assertion.addChainableMethod('change', assertChanges);
1946 | Assertion.addChainableMethod('changes', assertChanges);
1947 |
1948 | /**
1949 | * ### .increase(function)
1950 | *
1951 | * Asserts that a function increases an object property
1952 | *
1953 | * var obj = { val: 10 };
1954 | * var fn = function() { obj.val = 15 };
1955 | * expect(fn).to.increase(obj, 'val');
1956 | *
1957 | * @name increase
1958 | * @alias increases
1959 | * @alias Increase
1960 | * @param {String} object
1961 | * @param {String} property name
1962 | * @param {String} message _optional_
1963 | * @namespace BDD
1964 | * @api public
1965 | */
1966 |
1967 | function assertIncreases (object, prop, msg) {
1968 | if (msg) flag(this, 'message', msg);
1969 | var fn = flag(this, 'object');
1970 | new Assertion(object, msg).to.have.property(prop);
1971 | new Assertion(fn).is.a('function');
1972 |
1973 | var initial = object[prop];
1974 | fn();
1975 |
1976 | this.assert(
1977 | object[prop] - initial > 0
1978 | , 'expected .' + prop + ' to increase'
1979 | , 'expected .' + prop + ' to not increase'
1980 | );
1981 | }
1982 |
1983 | Assertion.addChainableMethod('increase', assertIncreases);
1984 | Assertion.addChainableMethod('increases', assertIncreases);
1985 |
1986 | /**
1987 | * ### .decrease(function)
1988 | *
1989 | * Asserts that a function decreases an object property
1990 | *
1991 | * var obj = { val: 10 };
1992 | * var fn = function() { obj.val = 5 };
1993 | * expect(fn).to.decrease(obj, 'val');
1994 | *
1995 | * @name decrease
1996 | * @alias decreases
1997 | * @alias Decrease
1998 | * @param {String} object
1999 | * @param {String} property name
2000 | * @param {String} message _optional_
2001 | * @namespace BDD
2002 | * @api public
2003 | */
2004 |
2005 | function assertDecreases (object, prop, msg) {
2006 | if (msg) flag(this, 'message', msg);
2007 | var fn = flag(this, 'object');
2008 | new Assertion(object, msg).to.have.property(prop);
2009 | new Assertion(fn).is.a('function');
2010 |
2011 | var initial = object[prop];
2012 | fn();
2013 |
2014 | this.assert(
2015 | object[prop] - initial < 0
2016 | , 'expected .' + prop + ' to decrease'
2017 | , 'expected .' + prop + ' to not decrease'
2018 | );
2019 | }
2020 |
2021 | Assertion.addChainableMethod('decrease', assertDecreases);
2022 | Assertion.addChainableMethod('decreases', assertDecreases);
2023 |
2024 | /**
2025 | * ### .extensible
2026 | *
2027 | * Asserts that the target is extensible (can have new properties added to
2028 | * it).
2029 | *
2030 | * var nonExtensibleObject = Object.preventExtensions({});
2031 | * var sealedObject = Object.seal({});
2032 | * var frozenObject = Object.freeze({});
2033 | *
2034 | * expect({}).to.be.extensible;
2035 | * expect(nonExtensibleObject).to.not.be.extensible;
2036 | * expect(sealedObject).to.not.be.extensible;
2037 | * expect(frozenObject).to.not.be.extensible;
2038 | *
2039 | * @name extensible
2040 | * @namespace BDD
2041 | * @api public
2042 | */
2043 |
2044 | Assertion.addProperty('extensible', function() {
2045 | var obj = flag(this, 'object');
2046 |
2047 | // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError.
2048 | // In ES6, a non-object argument will be treated as if it was a non-extensible ordinary object, simply return false.
2049 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isExtensible
2050 | // The following provides ES6 behavior when a TypeError is thrown under ES5.
2051 |
2052 | var isExtensible;
2053 |
2054 | try {
2055 | isExtensible = Object.isExtensible(obj);
2056 | } catch (err) {
2057 | if (err instanceof TypeError) isExtensible = false;
2058 | else throw err;
2059 | }
2060 |
2061 | this.assert(
2062 | isExtensible
2063 | , 'expected #{this} to be extensible'
2064 | , 'expected #{this} to not be extensible'
2065 | );
2066 | });
2067 |
2068 | /**
2069 | * ### .sealed
2070 | *
2071 | * Asserts that the target is sealed (cannot have new properties added to it
2072 | * and its existing properties cannot be removed).
2073 | *
2074 | * var sealedObject = Object.seal({});
2075 | * var frozenObject = Object.freeze({});
2076 | *
2077 | * expect(sealedObject).to.be.sealed;
2078 | * expect(frozenObject).to.be.sealed;
2079 | * expect({}).to.not.be.sealed;
2080 | *
2081 | * @name sealed
2082 | * @namespace BDD
2083 | * @api public
2084 | */
2085 |
2086 | Assertion.addProperty('sealed', function() {
2087 | var obj = flag(this, 'object');
2088 |
2089 | // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError.
2090 | // In ES6, a non-object argument will be treated as if it was a sealed ordinary object, simply return true.
2091 | // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isSealed
2092 | // The following provides ES6 behavior when a TypeError is thrown under ES5.
2093 |
2094 | var isSealed;
2095 |
2096 | try {
2097 | isSealed = Object.isSealed(obj);
2098 | } catch (err) {
2099 | if (err instanceof TypeError) isSealed = true;
2100 | else throw err;
2101 | }
2102 |
2103 | this.assert(
2104 | isSealed
2105 | , 'expected #{this} to be sealed'
2106 | , 'expected #{this} to not be sealed'
2107 | );
2108 | });
2109 |
2110 | /**
2111 | * ### .frozen
2112 | *
2113 | * Asserts that the target is frozen (cannot have new properties added to it
2114 | * and its existing properties cannot be modified).
2115 | *
2116 | * var frozenObject = Object.freeze({});
2117 | *
2118 | * expect(frozenObject).to.be.frozen;
2119 | * expect({}).to.not.be.frozen;
2120 | *
2121 | * @name frozen
2122 | * @namespace BDD
2123 | * @api public
2124 | */
2125 |
2126 | Assertion.addProperty('frozen', function() {
2127 | var obj = flag(this, 'object');
2128 |
2129 | // In ES5, if the argument to this method is not an object (a primitive), then it will cause a TypeError.
2130 | // In ES6, a non-object argument will be treated as if it was a frozen ordinary object, simply return true.
2131 | // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/isFrozen
2132 | // The following provides ES6 behavior when a TypeError is thrown under ES5.
2133 |
2134 | var isFrozen;
2135 |
2136 | try {
2137 | isFrozen = Object.isFrozen(obj);
2138 | } catch (err) {
2139 | if (err instanceof TypeError) isFrozen = true;
2140 | else throw err;
2141 | }
2142 |
2143 | this.assert(
2144 | isFrozen
2145 | , 'expected #{this} to be frozen'
2146 | , 'expected #{this} to not be frozen'
2147 | );
2148 | });
2149 | };
2150 |
2151 | },{}],6:[function(require,module,exports){
2152 | /*!
2153 | * chai
2154 | * Copyright(c) 2011-2014 Jake Luer
2155 | * MIT Licensed
2156 | */
2157 |
2158 |
2159 | module.exports = function (chai, util) {
2160 |
2161 | /*!
2162 | * Chai dependencies.
2163 | */
2164 |
2165 | var Assertion = chai.Assertion
2166 | , flag = util.flag;
2167 |
2168 | /*!
2169 | * Module export.
2170 | */
2171 |
2172 | /**
2173 | * ### assert(expression, message)
2174 | *
2175 | * Write your own test expressions.
2176 | *
2177 | * assert('foo' !== 'bar', 'foo is not bar');
2178 | * assert(Array.isArray([]), 'empty arrays are arrays');
2179 | *
2180 | * @param {Mixed} expression to test for truthiness
2181 | * @param {String} message to display on error
2182 | * @name assert
2183 | * @namespace Assert
2184 | * @api public
2185 | */
2186 |
2187 | var assert = chai.assert = function (express, errmsg) {
2188 | var test = new Assertion(null, null, chai.assert);
2189 | test.assert(
2190 | express
2191 | , errmsg
2192 | , '[ negation message unavailable ]'
2193 | );
2194 | };
2195 |
2196 | /**
2197 | * ### .fail(actual, expected, [message], [operator])
2198 | *
2199 | * Throw a failure. Node.js `assert` module-compatible.
2200 | *
2201 | * @name fail
2202 | * @param {Mixed} actual
2203 | * @param {Mixed} expected
2204 | * @param {String} message
2205 | * @param {String} operator
2206 | * @namespace Assert
2207 | * @api public
2208 | */
2209 |
2210 | assert.fail = function (actual, expected, message, operator) {
2211 | message = message || 'assert.fail()';
2212 | throw new chai.AssertionError(message, {
2213 | actual: actual
2214 | , expected: expected
2215 | , operator: operator
2216 | }, assert.fail);
2217 | };
2218 |
2219 | /**
2220 | * ### .isOk(object, [message])
2221 | *
2222 | * Asserts that `object` is truthy.
2223 | *
2224 | * assert.isOk('everything', 'everything is ok');
2225 | * assert.isOk(false, 'this will fail');
2226 | *
2227 | * @name isOk
2228 | * @alias ok
2229 | * @param {Mixed} object to test
2230 | * @param {String} message
2231 | * @namespace Assert
2232 | * @api public
2233 | */
2234 |
2235 | assert.isOk = function (val, msg) {
2236 | new Assertion(val, msg).is.ok;
2237 | };
2238 |
2239 | /**
2240 | * ### .isNotOk(object, [message])
2241 | *
2242 | * Asserts that `object` is falsy.
2243 | *
2244 | * assert.isNotOk('everything', 'this will fail');
2245 | * assert.isNotOk(false, 'this will pass');
2246 | *
2247 | * @name isNotOk
2248 | * @alias notOk
2249 | * @param {Mixed} object to test
2250 | * @param {String} message
2251 | * @namespace Assert
2252 | * @api public
2253 | */
2254 |
2255 | assert.isNotOk = function (val, msg) {
2256 | new Assertion(val, msg).is.not.ok;
2257 | };
2258 |
2259 | /**
2260 | * ### .equal(actual, expected, [message])
2261 | *
2262 | * Asserts non-strict equality (`==`) of `actual` and `expected`.
2263 | *
2264 | * assert.equal(3, '3', '== coerces values to strings');
2265 | *
2266 | * @name equal
2267 | * @param {Mixed} actual
2268 | * @param {Mixed} expected
2269 | * @param {String} message
2270 | * @namespace Assert
2271 | * @api public
2272 | */
2273 |
2274 | assert.equal = function (act, exp, msg) {
2275 | var test = new Assertion(act, msg, assert.equal);
2276 |
2277 | test.assert(
2278 | exp == flag(test, 'object')
2279 | , 'expected #{this} to equal #{exp}'
2280 | , 'expected #{this} to not equal #{act}'
2281 | , exp
2282 | , act
2283 | );
2284 | };
2285 |
2286 | /**
2287 | * ### .notEqual(actual, expected, [message])
2288 | *
2289 | * Asserts non-strict inequality (`!=`) of `actual` and `expected`.
2290 | *
2291 | * assert.notEqual(3, 4, 'these numbers are not equal');
2292 | *
2293 | * @name notEqual
2294 | * @param {Mixed} actual
2295 | * @param {Mixed} expected
2296 | * @param {String} message
2297 | * @namespace Assert
2298 | * @api public
2299 | */
2300 |
2301 | assert.notEqual = function (act, exp, msg) {
2302 | var test = new Assertion(act, msg, assert.notEqual);
2303 |
2304 | test.assert(
2305 | exp != flag(test, 'object')
2306 | , 'expected #{this} to not equal #{exp}'
2307 | , 'expected #{this} to equal #{act}'
2308 | , exp
2309 | , act
2310 | );
2311 | };
2312 |
2313 | /**
2314 | * ### .strictEqual(actual, expected, [message])
2315 | *
2316 | * Asserts strict equality (`===`) of `actual` and `expected`.
2317 | *
2318 | * assert.strictEqual(true, true, 'these booleans are strictly equal');
2319 | *
2320 | * @name strictEqual
2321 | * @param {Mixed} actual
2322 | * @param {Mixed} expected
2323 | * @param {String} message
2324 | * @namespace Assert
2325 | * @api public
2326 | */
2327 |
2328 | assert.strictEqual = function (act, exp, msg) {
2329 | new Assertion(act, msg).to.equal(exp);
2330 | };
2331 |
2332 | /**
2333 | * ### .notStrictEqual(actual, expected, [message])
2334 | *
2335 | * Asserts strict inequality (`!==`) of `actual` and `expected`.
2336 | *
2337 | * assert.notStrictEqual(3, '3', 'no coercion for strict equality');
2338 | *
2339 | * @name notStrictEqual
2340 | * @param {Mixed} actual
2341 | * @param {Mixed} expected
2342 | * @param {String} message
2343 | * @namespace Assert
2344 | * @api public
2345 | */
2346 |
2347 | assert.notStrictEqual = function (act, exp, msg) {
2348 | new Assertion(act, msg).to.not.equal(exp);
2349 | };
2350 |
2351 | /**
2352 | * ### .deepEqual(actual, expected, [message])
2353 | *
2354 | * Asserts that `actual` is deeply equal to `expected`.
2355 | *
2356 | * assert.deepEqual({ tea: 'green' }, { tea: 'green' });
2357 | *
2358 | * @name deepEqual
2359 | * @param {Mixed} actual
2360 | * @param {Mixed} expected
2361 | * @param {String} message
2362 | * @namespace Assert
2363 | * @api public
2364 | */
2365 |
2366 | assert.deepEqual = function (act, exp, msg) {
2367 | new Assertion(act, msg).to.eql(exp);
2368 | };
2369 |
2370 | /**
2371 | * ### .notDeepEqual(actual, expected, [message])
2372 | *
2373 | * Assert that `actual` is not deeply equal to `expected`.
2374 | *
2375 | * assert.notDeepEqual({ tea: 'green' }, { tea: 'jasmine' });
2376 | *
2377 | * @name notDeepEqual
2378 | * @param {Mixed} actual
2379 | * @param {Mixed} expected
2380 | * @param {String} message
2381 | * @namespace Assert
2382 | * @api public
2383 | */
2384 |
2385 | assert.notDeepEqual = function (act, exp, msg) {
2386 | new Assertion(act, msg).to.not.eql(exp);
2387 | };
2388 |
2389 | /**
2390 | * ### .isAbove(valueToCheck, valueToBeAbove, [message])
2391 | *
2392 | * Asserts `valueToCheck` is strictly greater than (>) `valueToBeAbove`
2393 | *
2394 | * assert.isAbove(5, 2, '5 is strictly greater than 2');
2395 | *
2396 | * @name isAbove
2397 | * @param {Mixed} valueToCheck
2398 | * @param {Mixed} valueToBeAbove
2399 | * @param {String} message
2400 | * @namespace Assert
2401 | * @api public
2402 | */
2403 |
2404 | assert.isAbove = function (val, abv, msg) {
2405 | new Assertion(val, msg).to.be.above(abv);
2406 | };
2407 |
2408 | /**
2409 | * ### .isAtLeast(valueToCheck, valueToBeAtLeast, [message])
2410 | *
2411 | * Asserts `valueToCheck` is greater than or equal to (>=) `valueToBeAtLeast`
2412 | *
2413 | * assert.isAtLeast(5, 2, '5 is greater or equal to 2');
2414 | * assert.isAtLeast(3, 3, '3 is greater or equal to 3');
2415 | *
2416 | * @name isAtLeast
2417 | * @param {Mixed} valueToCheck
2418 | * @param {Mixed} valueToBeAtLeast
2419 | * @param {String} message
2420 | * @namespace Assert
2421 | * @api public
2422 | */
2423 |
2424 | assert.isAtLeast = function (val, atlst, msg) {
2425 | new Assertion(val, msg).to.be.least(atlst);
2426 | };
2427 |
2428 | /**
2429 | * ### .isBelow(valueToCheck, valueToBeBelow, [message])
2430 | *
2431 | * Asserts `valueToCheck` is strictly less than (<) `valueToBeBelow`
2432 | *
2433 | * assert.isBelow(3, 6, '3 is strictly less than 6');
2434 | *
2435 | * @name isBelow
2436 | * @param {Mixed} valueToCheck
2437 | * @param {Mixed} valueToBeBelow
2438 | * @param {String} message
2439 | * @namespace Assert
2440 | * @api public
2441 | */
2442 |
2443 | assert.isBelow = function (val, blw, msg) {
2444 | new Assertion(val, msg).to.be.below(blw);
2445 | };
2446 |
2447 | /**
2448 | * ### .isAtMost(valueToCheck, valueToBeAtMost, [message])
2449 | *
2450 | * Asserts `valueToCheck` is less than or equal to (<=) `valueToBeAtMost`
2451 | *
2452 | * assert.isAtMost(3, 6, '3 is less than or equal to 6');
2453 | * assert.isAtMost(4, 4, '4 is less than or equal to 4');
2454 | *
2455 | * @name isAtMost
2456 | * @param {Mixed} valueToCheck
2457 | * @param {Mixed} valueToBeAtMost
2458 | * @param {String} message
2459 | * @namespace Assert
2460 | * @api public
2461 | */
2462 |
2463 | assert.isAtMost = function (val, atmst, msg) {
2464 | new Assertion(val, msg).to.be.most(atmst);
2465 | };
2466 |
2467 | /**
2468 | * ### .isTrue(value, [message])
2469 | *
2470 | * Asserts that `value` is true.
2471 | *
2472 | * var teaServed = true;
2473 | * assert.isTrue(teaServed, 'the tea has been served');
2474 | *
2475 | * @name isTrue
2476 | * @param {Mixed} value
2477 | * @param {String} message
2478 | * @namespace Assert
2479 | * @api public
2480 | */
2481 |
2482 | assert.isTrue = function (val, msg) {
2483 | new Assertion(val, msg).is['true'];
2484 | };
2485 |
2486 | /**
2487 | * ### .isNotTrue(value, [message])
2488 | *
2489 | * Asserts that `value` is not true.
2490 | *
2491 | * var tea = 'tasty chai';
2492 | * assert.isNotTrue(tea, 'great, time for tea!');
2493 | *
2494 | * @name isNotTrue
2495 | * @param {Mixed} value
2496 | * @param {String} message
2497 | * @namespace Assert
2498 | * @api public
2499 | */
2500 |
2501 | assert.isNotTrue = function (val, msg) {
2502 | new Assertion(val, msg).to.not.equal(true);
2503 | };
2504 |
2505 | /**
2506 | * ### .isFalse(value, [message])
2507 | *
2508 | * Asserts that `value` is false.
2509 | *
2510 | * var teaServed = false;
2511 | * assert.isFalse(teaServed, 'no tea yet? hmm...');
2512 | *
2513 | * @name isFalse
2514 | * @param {Mixed} value
2515 | * @param {String} message
2516 | * @namespace Assert
2517 | * @api public
2518 | */
2519 |
2520 | assert.isFalse = function (val, msg) {
2521 | new Assertion(val, msg).is['false'];
2522 | };
2523 |
2524 | /**
2525 | * ### .isNotFalse(value, [message])
2526 | *
2527 | * Asserts that `value` is not false.
2528 | *
2529 | * var tea = 'tasty chai';
2530 | * assert.isNotFalse(tea, 'great, time for tea!');
2531 | *
2532 | * @name isNotFalse
2533 | * @param {Mixed} value
2534 | * @param {String} message
2535 | * @namespace Assert
2536 | * @api public
2537 | */
2538 |
2539 | assert.isNotFalse = function (val, msg) {
2540 | new Assertion(val, msg).to.not.equal(false);
2541 | };
2542 |
2543 | /**
2544 | * ### .isNull(value, [message])
2545 | *
2546 | * Asserts that `value` is null.
2547 | *
2548 | * assert.isNull(err, 'there was no error');
2549 | *
2550 | * @name isNull
2551 | * @param {Mixed} value
2552 | * @param {String} message
2553 | * @namespace Assert
2554 | * @api public
2555 | */
2556 |
2557 | assert.isNull = function (val, msg) {
2558 | new Assertion(val, msg).to.equal(null);
2559 | };
2560 |
2561 | /**
2562 | * ### .isNotNull(value, [message])
2563 | *
2564 | * Asserts that `value` is not null.
2565 | *
2566 | * var tea = 'tasty chai';
2567 | * assert.isNotNull(tea, 'great, time for tea!');
2568 | *
2569 | * @name isNotNull
2570 | * @param {Mixed} value
2571 | * @param {String} message
2572 | * @namespace Assert
2573 | * @api public
2574 | */
2575 |
2576 | assert.isNotNull = function (val, msg) {
2577 | new Assertion(val, msg).to.not.equal(null);
2578 | };
2579 |
2580 | /**
2581 | * ### .isNaN
2582 | * Asserts that value is NaN
2583 | *
2584 | * assert.isNaN('foo', 'foo is NaN');
2585 | *
2586 | * @name isNaN
2587 | * @param {Mixed} value
2588 | * @param {String} message
2589 | * @namespace Assert
2590 | * @api public
2591 | */
2592 |
2593 | assert.isNaN = function (val, msg) {
2594 | new Assertion(val, msg).to.be.NaN;
2595 | };
2596 |
2597 | /**
2598 | * ### .isNotNaN
2599 | * Asserts that value is not NaN
2600 | *
2601 | * assert.isNotNaN(4, '4 is not NaN');
2602 | *
2603 | * @name isNotNaN
2604 | * @param {Mixed} value
2605 | * @param {String} message
2606 | * @namespace Assert
2607 | * @api public
2608 | */
2609 | assert.isNotNaN = function (val, msg) {
2610 | new Assertion(val, msg).not.to.be.NaN;
2611 | };
2612 |
2613 | /**
2614 | * ### .isUndefined(value, [message])
2615 | *
2616 | * Asserts that `value` is `undefined`.
2617 | *
2618 | * var tea;
2619 | * assert.isUndefined(tea, 'no tea defined');
2620 | *
2621 | * @name isUndefined
2622 | * @param {Mixed} value
2623 | * @param {String} message
2624 | * @namespace Assert
2625 | * @api public
2626 | */
2627 |
2628 | assert.isUndefined = function (val, msg) {
2629 | new Assertion(val, msg).to.equal(undefined);
2630 | };
2631 |
2632 | /**
2633 | * ### .isDefined(value, [message])
2634 | *
2635 | * Asserts that `value` is not `undefined`.
2636 | *
2637 | * var tea = 'cup of chai';
2638 | * assert.isDefined(tea, 'tea has been defined');
2639 | *
2640 | * @name isDefined
2641 | * @param {Mixed} value
2642 | * @param {String} message
2643 | * @namespace Assert
2644 | * @api public
2645 | */
2646 |
2647 | assert.isDefined = function (val, msg) {
2648 | new Assertion(val, msg).to.not.equal(undefined);
2649 | };
2650 |
2651 | /**
2652 | * ### .isFunction(value, [message])
2653 | *
2654 | * Asserts that `value` is a function.
2655 | *
2656 | * function serveTea() { return 'cup of tea'; };
2657 | * assert.isFunction(serveTea, 'great, we can have tea now');
2658 | *
2659 | * @name isFunction
2660 | * @param {Mixed} value
2661 | * @param {String} message
2662 | * @namespace Assert
2663 | * @api public
2664 | */
2665 |
2666 | assert.isFunction = function (val, msg) {
2667 | new Assertion(val, msg).to.be.a('function');
2668 | };
2669 |
2670 | /**
2671 | * ### .isNotFunction(value, [message])
2672 | *
2673 | * Asserts that `value` is _not_ a function.
2674 | *
2675 | * var serveTea = [ 'heat', 'pour', 'sip' ];
2676 | * assert.isNotFunction(serveTea, 'great, we have listed the steps');
2677 | *
2678 | * @name isNotFunction
2679 | * @param {Mixed} value
2680 | * @param {String} message
2681 | * @namespace Assert
2682 | * @api public
2683 | */
2684 |
2685 | assert.isNotFunction = function (val, msg) {
2686 | new Assertion(val, msg).to.not.be.a('function');
2687 | };
2688 |
2689 | /**
2690 | * ### .isObject(value, [message])
2691 | *
2692 | * Asserts that `value` is an object of type 'Object' (as revealed by `Object.prototype.toString`).
2693 | * _The assertion does not match subclassed objects._
2694 | *
2695 | * var selection = { name: 'Chai', serve: 'with spices' };
2696 | * assert.isObject(selection, 'tea selection is an object');
2697 | *
2698 | * @name isObject
2699 | * @param {Mixed} value
2700 | * @param {String} message
2701 | * @namespace Assert
2702 | * @api public
2703 | */
2704 |
2705 | assert.isObject = function (val, msg) {
2706 | new Assertion(val, msg).to.be.a('object');
2707 | };
2708 |
2709 | /**
2710 | * ### .isNotObject(value, [message])
2711 | *
2712 | * Asserts that `value` is _not_ an object of type 'Object' (as revealed by `Object.prototype.toString`).
2713 | *
2714 | * var selection = 'chai'
2715 | * assert.isNotObject(selection, 'tea selection is not an object');
2716 | * assert.isNotObject(null, 'null is not an object');
2717 | *
2718 | * @name isNotObject
2719 | * @param {Mixed} value
2720 | * @param {String} message
2721 | * @namespace Assert
2722 | * @api public
2723 | */
2724 |
2725 | assert.isNotObject = function (val, msg) {
2726 | new Assertion(val, msg).to.not.be.a('object');
2727 | };
2728 |
2729 | /**
2730 | * ### .isArray(value, [message])
2731 | *
2732 | * Asserts that `value` is an array.
2733 | *
2734 | * var menu = [ 'green', 'chai', 'oolong' ];
2735 | * assert.isArray(menu, 'what kind of tea do we want?');
2736 | *
2737 | * @name isArray
2738 | * @param {Mixed} value
2739 | * @param {String} message
2740 | * @namespace Assert
2741 | * @api public
2742 | */
2743 |
2744 | assert.isArray = function (val, msg) {
2745 | new Assertion(val, msg).to.be.an('array');
2746 | };
2747 |
2748 | /**
2749 | * ### .isNotArray(value, [message])
2750 | *
2751 | * Asserts that `value` is _not_ an array.
2752 | *
2753 | * var menu = 'green|chai|oolong';
2754 | * assert.isNotArray(menu, 'what kind of tea do we want?');
2755 | *
2756 | * @name isNotArray
2757 | * @param {Mixed} value
2758 | * @param {String} message
2759 | * @namespace Assert
2760 | * @api public
2761 | */
2762 |
2763 | assert.isNotArray = function (val, msg) {
2764 | new Assertion(val, msg).to.not.be.an('array');
2765 | };
2766 |
2767 | /**
2768 | * ### .isString(value, [message])
2769 | *
2770 | * Asserts that `value` is a string.
2771 | *
2772 | * var teaOrder = 'chai';
2773 | * assert.isString(teaOrder, 'order placed');
2774 | *
2775 | * @name isString
2776 | * @param {Mixed} value
2777 | * @param {String} message
2778 | * @namespace Assert
2779 | * @api public
2780 | */
2781 |
2782 | assert.isString = function (val, msg) {
2783 | new Assertion(val, msg).to.be.a('string');
2784 | };
2785 |
2786 | /**
2787 | * ### .isNotString(value, [message])
2788 | *
2789 | * Asserts that `value` is _not_ a string.
2790 | *
2791 | * var teaOrder = 4;
2792 | * assert.isNotString(teaOrder, 'order placed');
2793 | *
2794 | * @name isNotString
2795 | * @param {Mixed} value
2796 | * @param {String} message
2797 | * @namespace Assert
2798 | * @api public
2799 | */
2800 |
2801 | assert.isNotString = function (val, msg) {
2802 | new Assertion(val, msg).to.not.be.a('string');
2803 | };
2804 |
2805 | /**
2806 | * ### .isNumber(value, [message])
2807 | *
2808 | * Asserts that `value` is a number.
2809 | *
2810 | * var cups = 2;
2811 | * assert.isNumber(cups, 'how many cups');
2812 | *
2813 | * @name isNumber
2814 | * @param {Number} value
2815 | * @param {String} message
2816 | * @namespace Assert
2817 | * @api public
2818 | */
2819 |
2820 | assert.isNumber = function (val, msg) {
2821 | new Assertion(val, msg).to.be.a('number');
2822 | };
2823 |
2824 | /**
2825 | * ### .isNotNumber(value, [message])
2826 | *
2827 | * Asserts that `value` is _not_ a number.
2828 | *
2829 | * var cups = '2 cups please';
2830 | * assert.isNotNumber(cups, 'how many cups');
2831 | *
2832 | * @name isNotNumber
2833 | * @param {Mixed} value
2834 | * @param {String} message
2835 | * @namespace Assert
2836 | * @api public
2837 | */
2838 |
2839 | assert.isNotNumber = function (val, msg) {
2840 | new Assertion(val, msg).to.not.be.a('number');
2841 | };
2842 |
2843 | /**
2844 | * ### .isBoolean(value, [message])
2845 | *
2846 | * Asserts that `value` is a boolean.
2847 | *
2848 | * var teaReady = true
2849 | * , teaServed = false;
2850 | *
2851 | * assert.isBoolean(teaReady, 'is the tea ready');
2852 | * assert.isBoolean(teaServed, 'has tea been served');
2853 | *
2854 | * @name isBoolean
2855 | * @param {Mixed} value
2856 | * @param {String} message
2857 | * @namespace Assert
2858 | * @api public
2859 | */
2860 |
2861 | assert.isBoolean = function (val, msg) {
2862 | new Assertion(val, msg).to.be.a('boolean');
2863 | };
2864 |
2865 | /**
2866 | * ### .isNotBoolean(value, [message])
2867 | *
2868 | * Asserts that `value` is _not_ a boolean.
2869 | *
2870 | * var teaReady = 'yep'
2871 | * , teaServed = 'nope';
2872 | *
2873 | * assert.isNotBoolean(teaReady, 'is the tea ready');
2874 | * assert.isNotBoolean(teaServed, 'has tea been served');
2875 | *
2876 | * @name isNotBoolean
2877 | * @param {Mixed} value
2878 | * @param {String} message
2879 | * @namespace Assert
2880 | * @api public
2881 | */
2882 |
2883 | assert.isNotBoolean = function (val, msg) {
2884 | new Assertion(val, msg).to.not.be.a('boolean');
2885 | };
2886 |
2887 | /**
2888 | * ### .typeOf(value, name, [message])
2889 | *
2890 | * Asserts that `value`'s type is `name`, as determined by
2891 | * `Object.prototype.toString`.
2892 | *
2893 | * assert.typeOf({ tea: 'chai' }, 'object', 'we have an object');
2894 | * assert.typeOf(['chai', 'jasmine'], 'array', 'we have an array');
2895 | * assert.typeOf('tea', 'string', 'we have a string');
2896 | * assert.typeOf(/tea/, 'regexp', 'we have a regular expression');
2897 | * assert.typeOf(null, 'null', 'we have a null');
2898 | * assert.typeOf(undefined, 'undefined', 'we have an undefined');
2899 | *
2900 | * @name typeOf
2901 | * @param {Mixed} value
2902 | * @param {String} name
2903 | * @param {String} message
2904 | * @namespace Assert
2905 | * @api public
2906 | */
2907 |
2908 | assert.typeOf = function (val, type, msg) {
2909 | new Assertion(val, msg).to.be.a(type);
2910 | };
2911 |
2912 | /**
2913 | * ### .notTypeOf(value, name, [message])
2914 | *
2915 | * Asserts that `value`'s type is _not_ `name`, as determined by
2916 | * `Object.prototype.toString`.
2917 | *
2918 | * assert.notTypeOf('tea', 'number', 'strings are not numbers');
2919 | *
2920 | * @name notTypeOf
2921 | * @param {Mixed} value
2922 | * @param {String} typeof name
2923 | * @param {String} message
2924 | * @namespace Assert
2925 | * @api public
2926 | */
2927 |
2928 | assert.notTypeOf = function (val, type, msg) {
2929 | new Assertion(val, msg).to.not.be.a(type);
2930 | };
2931 |
2932 | /**
2933 | * ### .instanceOf(object, constructor, [message])
2934 | *
2935 | * Asserts that `value` is an instance of `constructor`.
2936 | *
2937 | * var Tea = function (name) { this.name = name; }
2938 | * , chai = new Tea('chai');
2939 | *
2940 | * assert.instanceOf(chai, Tea, 'chai is an instance of tea');
2941 | *
2942 | * @name instanceOf
2943 | * @param {Object} object
2944 | * @param {Constructor} constructor
2945 | * @param {String} message
2946 | * @namespace Assert
2947 | * @api public
2948 | */
2949 |
2950 | assert.instanceOf = function (val, type, msg) {
2951 | new Assertion(val, msg).to.be.instanceOf(type);
2952 | };
2953 |
2954 | /**
2955 | * ### .notInstanceOf(object, constructor, [message])
2956 | *
2957 | * Asserts `value` is not an instance of `constructor`.
2958 | *
2959 | * var Tea = function (name) { this.name = name; }
2960 | * , chai = new String('chai');
2961 | *
2962 | * assert.notInstanceOf(chai, Tea, 'chai is not an instance of tea');
2963 | *
2964 | * @name notInstanceOf
2965 | * @param {Object} object
2966 | * @param {Constructor} constructor
2967 | * @param {String} message
2968 | * @namespace Assert
2969 | * @api public
2970 | */
2971 |
2972 | assert.notInstanceOf = function (val, type, msg) {
2973 | new Assertion(val, msg).to.not.be.instanceOf(type);
2974 | };
2975 |
2976 | /**
2977 | * ### .include(haystack, needle, [message])
2978 | *
2979 | * Asserts that `haystack` includes `needle`. Works
2980 | * for strings and arrays.
2981 | *
2982 | * assert.include('foobar', 'bar', 'foobar contains string "bar"');
2983 | * assert.include([ 1, 2, 3 ], 3, 'array contains value');
2984 | *
2985 | * @name include
2986 | * @param {Array|String} haystack
2987 | * @param {Mixed} needle
2988 | * @param {String} message
2989 | * @namespace Assert
2990 | * @api public
2991 | */
2992 |
2993 | assert.include = function (exp, inc, msg) {
2994 | new Assertion(exp, msg, assert.include).include(inc);
2995 | };
2996 |
2997 | /**
2998 | * ### .notInclude(haystack, needle, [message])
2999 | *
3000 | * Asserts that `haystack` does not include `needle`. Works
3001 | * for strings and arrays.
3002 | *
3003 | * assert.notInclude('foobar', 'baz', 'string not include substring');
3004 | * assert.notInclude([ 1, 2, 3 ], 4, 'array not include contain value');
3005 | *
3006 | * @name notInclude
3007 | * @param {Array|String} haystack
3008 | * @param {Mixed} needle
3009 | * @param {String} message
3010 | * @namespace Assert
3011 | * @api public
3012 | */
3013 |
3014 | assert.notInclude = function (exp, inc, msg) {
3015 | new Assertion(exp, msg, assert.notInclude).not.include(inc);
3016 | };
3017 |
3018 | /**
3019 | * ### .match(value, regexp, [message])
3020 | *
3021 | * Asserts that `value` matches the regular expression `regexp`.
3022 | *
3023 | * assert.match('foobar', /^foo/, 'regexp matches');
3024 | *
3025 | * @name match
3026 | * @param {Mixed} value
3027 | * @param {RegExp} regexp
3028 | * @param {String} message
3029 | * @namespace Assert
3030 | * @api public
3031 | */
3032 |
3033 | assert.match = function (exp, re, msg) {
3034 | new Assertion(exp, msg).to.match(re);
3035 | };
3036 |
3037 | /**
3038 | * ### .notMatch(value, regexp, [message])
3039 | *
3040 | * Asserts that `value` does not match the regular expression `regexp`.
3041 | *
3042 | * assert.notMatch('foobar', /^foo/, 'regexp does not match');
3043 | *
3044 | * @name notMatch
3045 | * @param {Mixed} value
3046 | * @param {RegExp} regexp
3047 | * @param {String} message
3048 | * @namespace Assert
3049 | * @api public
3050 | */
3051 |
3052 | assert.notMatch = function (exp, re, msg) {
3053 | new Assertion(exp, msg).to.not.match(re);
3054 | };
3055 |
3056 | /**
3057 | * ### .property(object, property, [message])
3058 | *
3059 | * Asserts that `object` has a property named by `property`.
3060 | *
3061 | * assert.property({ tea: { green: 'matcha' }}, 'tea');
3062 | *
3063 | * @name property
3064 | * @param {Object} object
3065 | * @param {String} property
3066 | * @param {String} message
3067 | * @namespace Assert
3068 | * @api public
3069 | */
3070 |
3071 | assert.property = function (obj, prop, msg) {
3072 | new Assertion(obj, msg).to.have.property(prop);
3073 | };
3074 |
3075 | /**
3076 | * ### .notProperty(object, property, [message])
3077 | *
3078 | * Asserts that `object` does _not_ have a property named by `property`.
3079 | *
3080 | * assert.notProperty({ tea: { green: 'matcha' }}, 'coffee');
3081 | *
3082 | * @name notProperty
3083 | * @param {Object} object
3084 | * @param {String} property
3085 | * @param {String} message
3086 | * @namespace Assert
3087 | * @api public
3088 | */
3089 |
3090 | assert.notProperty = function (obj, prop, msg) {
3091 | new Assertion(obj, msg).to.not.have.property(prop);
3092 | };
3093 |
3094 | /**
3095 | * ### .deepProperty(object, property, [message])
3096 | *
3097 | * Asserts that `object` has a property named by `property`, which can be a
3098 | * string using dot- and bracket-notation for deep reference.
3099 | *
3100 | * assert.deepProperty({ tea: { green: 'matcha' }}, 'tea.green');
3101 | *
3102 | * @name deepProperty
3103 | * @param {Object} object
3104 | * @param {String} property
3105 | * @param {String} message
3106 | * @namespace Assert
3107 | * @api public
3108 | */
3109 |
3110 | assert.deepProperty = function (obj, prop, msg) {
3111 | new Assertion(obj, msg).to.have.deep.property(prop);
3112 | };
3113 |
3114 | /**
3115 | * ### .notDeepProperty(object, property, [message])
3116 | *
3117 | * Asserts that `object` does _not_ have a property named by `property`, which
3118 | * can be a string using dot- and bracket-notation for deep reference.
3119 | *
3120 | * assert.notDeepProperty({ tea: { green: 'matcha' }}, 'tea.oolong');
3121 | *
3122 | * @name notDeepProperty
3123 | * @param {Object} object
3124 | * @param {String} property
3125 | * @param {String} message
3126 | * @namespace Assert
3127 | * @api public
3128 | */
3129 |
3130 | assert.notDeepProperty = function (obj, prop, msg) {
3131 | new Assertion(obj, msg).to.not.have.deep.property(prop);
3132 | };
3133 |
3134 | /**
3135 | * ### .propertyVal(object, property, value, [message])
3136 | *
3137 | * Asserts that `object` has a property named by `property` with value given
3138 | * by `value`.
3139 | *
3140 | * assert.propertyVal({ tea: 'is good' }, 'tea', 'is good');
3141 | *
3142 | * @name propertyVal
3143 | * @param {Object} object
3144 | * @param {String} property
3145 | * @param {Mixed} value
3146 | * @param {String} message
3147 | * @namespace Assert
3148 | * @api public
3149 | */
3150 |
3151 | assert.propertyVal = function (obj, prop, val, msg) {
3152 | new Assertion(obj, msg).to.have.property(prop, val);
3153 | };
3154 |
3155 | /**
3156 | * ### .propertyNotVal(object, property, value, [message])
3157 | *
3158 | * Asserts that `object` has a property named by `property`, but with a value
3159 | * different from that given by `value`.
3160 | *
3161 | * assert.propertyNotVal({ tea: 'is good' }, 'tea', 'is bad');
3162 | *
3163 | * @name propertyNotVal
3164 | * @param {Object} object
3165 | * @param {String} property
3166 | * @param {Mixed} value
3167 | * @param {String} message
3168 | * @namespace Assert
3169 | * @api public
3170 | */
3171 |
3172 | assert.propertyNotVal = function (obj, prop, val, msg) {
3173 | new Assertion(obj, msg).to.not.have.property(prop, val);
3174 | };
3175 |
3176 | /**
3177 | * ### .deepPropertyVal(object, property, value, [message])
3178 | *
3179 | * Asserts that `object` has a property named by `property` with value given
3180 | * by `value`. `property` can use dot- and bracket-notation for deep
3181 | * reference.
3182 | *
3183 | * assert.deepPropertyVal({ tea: { green: 'matcha' }}, 'tea.green', 'matcha');
3184 | *
3185 | * @name deepPropertyVal
3186 | * @param {Object} object
3187 | * @param {String} property
3188 | * @param {Mixed} value
3189 | * @param {String} message
3190 | * @namespace Assert
3191 | * @api public
3192 | */
3193 |
3194 | assert.deepPropertyVal = function (obj, prop, val, msg) {
3195 | new Assertion(obj, msg).to.have.deep.property(prop, val);
3196 | };
3197 |
3198 | /**
3199 | * ### .deepPropertyNotVal(object, property, value, [message])
3200 | *
3201 | * Asserts that `object` has a property named by `property`, but with a value
3202 | * different from that given by `value`. `property` can use dot- and
3203 | * bracket-notation for deep reference.
3204 | *
3205 | * assert.deepPropertyNotVal({ tea: { green: 'matcha' }}, 'tea.green', 'konacha');
3206 | *
3207 | * @name deepPropertyNotVal
3208 | * @param {Object} object
3209 | * @param {String} property
3210 | * @param {Mixed} value
3211 | * @param {String} message
3212 | * @namespace Assert
3213 | * @api public
3214 | */
3215 |
3216 | assert.deepPropertyNotVal = function (obj, prop, val, msg) {
3217 | new Assertion(obj, msg).to.not.have.deep.property(prop, val);
3218 | };
3219 |
3220 | /**
3221 | * ### .lengthOf(object, length, [message])
3222 | *
3223 | * Asserts that `object` has a `length` property with the expected value.
3224 | *
3225 | * assert.lengthOf([1,2,3], 3, 'array has length of 3');
3226 | * assert.lengthOf('foobar', 6, 'string has length of 6');
3227 | *
3228 | * @name lengthOf
3229 | * @param {Mixed} object
3230 | * @param {Number} length
3231 | * @param {String} message
3232 | * @namespace Assert
3233 | * @api public
3234 | */
3235 |
3236 | assert.lengthOf = function (exp, len, msg) {
3237 | new Assertion(exp, msg).to.have.length(len);
3238 | };
3239 |
3240 | /**
3241 | * ### .throws(function, [constructor/string/regexp], [string/regexp], [message])
3242 | *
3243 | * Asserts that `function` will throw an error that is an instance of
3244 | * `constructor`, or alternately that it will throw an error with message
3245 | * matching `regexp`.
3246 | *
3247 | * assert.throws(fn, 'function throws a reference error');
3248 | * assert.throws(fn, /function throws a reference error/);
3249 | * assert.throws(fn, ReferenceError);
3250 | * assert.throws(fn, ReferenceError, 'function throws a reference error');
3251 | * assert.throws(fn, ReferenceError, /function throws a reference error/);
3252 | *
3253 | * @name throws
3254 | * @alias throw
3255 | * @alias Throw
3256 | * @param {Function} function
3257 | * @param {ErrorConstructor} constructor
3258 | * @param {RegExp} regexp
3259 | * @param {String} message
3260 | * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
3261 | * @namespace Assert
3262 | * @api public
3263 | */
3264 |
3265 | assert.throws = function (fn, errt, errs, msg) {
3266 | if ('string' === typeof errt || errt instanceof RegExp) {
3267 | errs = errt;
3268 | errt = null;
3269 | }
3270 |
3271 | var assertErr = new Assertion(fn, msg).to.throw(errt, errs);
3272 | return flag(assertErr, 'object');
3273 | };
3274 |
3275 | /**
3276 | * ### .doesNotThrow(function, [constructor/regexp], [message])
3277 | *
3278 | * Asserts that `function` will _not_ throw an error that is an instance of
3279 | * `constructor`, or alternately that it will not throw an error with message
3280 | * matching `regexp`.
3281 | *
3282 | * assert.doesNotThrow(fn, Error, 'function does not throw');
3283 | *
3284 | * @name doesNotThrow
3285 | * @param {Function} function
3286 | * @param {ErrorConstructor} constructor
3287 | * @param {RegExp} regexp
3288 | * @param {String} message
3289 | * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
3290 | * @namespace Assert
3291 | * @api public
3292 | */
3293 |
3294 | assert.doesNotThrow = function (fn, type, msg) {
3295 | if ('string' === typeof type) {
3296 | msg = type;
3297 | type = null;
3298 | }
3299 |
3300 | new Assertion(fn, msg).to.not.Throw(type);
3301 | };
3302 |
3303 | /**
3304 | * ### .operator(val1, operator, val2, [message])
3305 | *
3306 | * Compares two values using `operator`.
3307 | *
3308 | * assert.operator(1, '<', 2, 'everything is ok');
3309 | * assert.operator(1, '>', 2, 'this will fail');
3310 | *
3311 | * @name operator
3312 | * @param {Mixed} val1
3313 | * @param {String} operator
3314 | * @param {Mixed} val2
3315 | * @param {String} message
3316 | * @namespace Assert
3317 | * @api public
3318 | */
3319 |
3320 | assert.operator = function (val, operator, val2, msg) {
3321 | var ok;
3322 | switch(operator) {
3323 | case '==':
3324 | ok = val == val2;
3325 | break;
3326 | case '===':
3327 | ok = val === val2;
3328 | break;
3329 | case '>':
3330 | ok = val > val2;
3331 | break;
3332 | case '>=':
3333 | ok = val >= val2;
3334 | break;
3335 | case '<':
3336 | ok = val < val2;
3337 | break;
3338 | case '<=':
3339 | ok = val <= val2;
3340 | break;
3341 | case '!=':
3342 | ok = val != val2;
3343 | break;
3344 | case '!==':
3345 | ok = val !== val2;
3346 | break;
3347 | default:
3348 | throw new Error('Invalid operator "' + operator + '"');
3349 | }
3350 | var test = new Assertion(ok, msg);
3351 | test.assert(
3352 | true === flag(test, 'object')
3353 | , 'expected ' + util.inspect(val) + ' to be ' + operator + ' ' + util.inspect(val2)
3354 | , 'expected ' + util.inspect(val) + ' to not be ' + operator + ' ' + util.inspect(val2) );
3355 | };
3356 |
3357 | /**
3358 | * ### .closeTo(actual, expected, delta, [message])
3359 | *
3360 | * Asserts that the target is equal `expected`, to within a +/- `delta` range.
3361 | *
3362 | * assert.closeTo(1.5, 1, 0.5, 'numbers are close');
3363 | *
3364 | * @name closeTo
3365 | * @param {Number} actual
3366 | * @param {Number} expected
3367 | * @param {Number} delta
3368 | * @param {String} message
3369 | * @namespace Assert
3370 | * @api public
3371 | */
3372 |
3373 | assert.closeTo = function (act, exp, delta, msg) {
3374 | new Assertion(act, msg).to.be.closeTo(exp, delta);
3375 | };
3376 |
3377 | /**
3378 | * ### .approximately(actual, expected, delta, [message])
3379 | *
3380 | * Asserts that the target is equal `expected`, to within a +/- `delta` range.
3381 | *
3382 | * assert.approximately(1.5, 1, 0.5, 'numbers are close');
3383 | *
3384 | * @name approximately
3385 | * @param {Number} actual
3386 | * @param {Number} expected
3387 | * @param {Number} delta
3388 | * @param {String} message
3389 | * @namespace Assert
3390 | * @api public
3391 | */
3392 |
3393 | assert.approximately = function (act, exp, delta, msg) {
3394 | new Assertion(act, msg).to.be.approximately(exp, delta);
3395 | };
3396 |
3397 | /**
3398 | * ### .sameMembers(set1, set2, [message])
3399 | *
3400 | * Asserts that `set1` and `set2` have the same members.
3401 | * Order is not taken into account.
3402 | *
3403 | * assert.sameMembers([ 1, 2, 3 ], [ 2, 1, 3 ], 'same members');
3404 | *
3405 | * @name sameMembers
3406 | * @param {Array} set1
3407 | * @param {Array} set2
3408 | * @param {String} message
3409 | * @namespace Assert
3410 | * @api public
3411 | */
3412 |
3413 | assert.sameMembers = function (set1, set2, msg) {
3414 | new Assertion(set1, msg).to.have.same.members(set2);
3415 | }
3416 |
3417 | /**
3418 | * ### .sameDeepMembers(set1, set2, [message])
3419 | *
3420 | * Asserts that `set1` and `set2` have the same members - using a deep equality checking.
3421 | * Order is not taken into account.
3422 | *
3423 | * assert.sameDeepMembers([ {b: 3}, {a: 2}, {c: 5} ], [ {c: 5}, {b: 3}, {a: 2} ], 'same deep members');
3424 | *
3425 | * @name sameDeepMembers
3426 | * @param {Array} set1
3427 | * @param {Array} set2
3428 | * @param {String} message
3429 | * @namespace Assert
3430 | * @api public
3431 | */
3432 |
3433 | assert.sameDeepMembers = function (set1, set2, msg) {
3434 | new Assertion(set1, msg).to.have.same.deep.members(set2);
3435 | }
3436 |
3437 | /**
3438 | * ### .includeMembers(superset, subset, [message])
3439 | *
3440 | * Asserts that `subset` is included in `superset`.
3441 | * Order is not taken into account.
3442 | *
3443 | * assert.includeMembers([ 1, 2, 3 ], [ 2, 1 ], 'include members');
3444 | *
3445 | * @name includeMembers
3446 | * @param {Array} superset
3447 | * @param {Array} subset
3448 | * @param {String} message
3449 | * @namespace Assert
3450 | * @api public
3451 | */
3452 |
3453 | assert.includeMembers = function (superset, subset, msg) {
3454 | new Assertion(superset, msg).to.include.members(subset);
3455 | }
3456 |
3457 | /**
3458 | * ### .includeDeepMembers(superset, subset, [message])
3459 | *
3460 | * Asserts that `subset` is included in `superset` - using deep equality checking.
3461 | * Order is not taken into account.
3462 | * Duplicates are ignored.
3463 | *
3464 | * assert.includeDeepMembers([ {a: 1}, {b: 2}, {c: 3} ], [ {b: 2}, {a: 1}, {b: 2} ], 'include deep members');
3465 | *
3466 | * @name includeDeepMembers
3467 | * @param {Array} superset
3468 | * @param {Array} subset
3469 | * @param {String} message
3470 | * @namespace Assert
3471 | * @api public
3472 | */
3473 |
3474 | assert.includeDeepMembers = function (superset, subset, msg) {
3475 | new Assertion(superset, msg).to.include.deep.members(subset);
3476 | }
3477 |
3478 | /**
3479 | * ### .oneOf(inList, list, [message])
3480 | *
3481 | * Asserts that non-object, non-array value `inList` appears in the flat array `list`.
3482 | *
3483 | * assert.oneOf(1, [ 2, 1 ], 'Not found in list');
3484 | *
3485 | * @name oneOf
3486 | * @param {*} inList
3487 | * @param {Array<*>} list
3488 | * @param {String} message
3489 | * @namespace Assert
3490 | * @api public
3491 | */
3492 |
3493 | assert.oneOf = function (inList, list, msg) {
3494 | new Assertion(inList, msg).to.be.oneOf(list);
3495 | }
3496 |
3497 | /**
3498 | * ### .changes(function, object, property)
3499 | *
3500 | * Asserts that a function changes the value of a property
3501 | *
3502 | * var obj = { val: 10 };
3503 | * var fn = function() { obj.val = 22 };
3504 | * assert.changes(fn, obj, 'val');
3505 | *
3506 | * @name changes
3507 | * @param {Function} modifier function
3508 | * @param {Object} object
3509 | * @param {String} property name
3510 | * @param {String} message _optional_
3511 | * @namespace Assert
3512 | * @api public
3513 | */
3514 |
3515 | assert.changes = function (fn, obj, prop) {
3516 | new Assertion(fn).to.change(obj, prop);
3517 | }
3518 |
3519 | /**
3520 | * ### .doesNotChange(function, object, property)
3521 | *
3522 | * Asserts that a function does not changes the value of a property
3523 | *
3524 | * var obj = { val: 10 };
3525 | * var fn = function() { console.log('foo'); };
3526 | * assert.doesNotChange(fn, obj, 'val');
3527 | *
3528 | * @name doesNotChange
3529 | * @param {Function} modifier function
3530 | * @param {Object} object
3531 | * @param {String} property name
3532 | * @param {String} message _optional_
3533 | * @namespace Assert
3534 | * @api public
3535 | */
3536 |
3537 | assert.doesNotChange = function (fn, obj, prop) {
3538 | new Assertion(fn).to.not.change(obj, prop);
3539 | }
3540 |
3541 | /**
3542 | * ### .increases(function, object, property)
3543 | *
3544 | * Asserts that a function increases an object property
3545 | *
3546 | * var obj = { val: 10 };
3547 | * var fn = function() { obj.val = 13 };
3548 | * assert.increases(fn, obj, 'val');
3549 | *
3550 | * @name increases
3551 | * @param {Function} modifier function
3552 | * @param {Object} object
3553 | * @param {String} property name
3554 | * @param {String} message _optional_
3555 | * @namespace Assert
3556 | * @api public
3557 | */
3558 |
3559 | assert.increases = function (fn, obj, prop) {
3560 | new Assertion(fn).to.increase(obj, prop);
3561 | }
3562 |
3563 | /**
3564 | * ### .doesNotIncrease(function, object, property)
3565 | *
3566 | * Asserts that a function does not increase object property
3567 | *
3568 | * var obj = { val: 10 };
3569 | * var fn = function() { obj.val = 8 };
3570 | * assert.doesNotIncrease(fn, obj, 'val');
3571 | *
3572 | * @name doesNotIncrease
3573 | * @param {Function} modifier function
3574 | * @param {Object} object
3575 | * @param {String} property name
3576 | * @param {String} message _optional_
3577 | * @namespace Assert
3578 | * @api public
3579 | */
3580 |
3581 | assert.doesNotIncrease = function (fn, obj, prop) {
3582 | new Assertion(fn).to.not.increase(obj, prop);
3583 | }
3584 |
3585 | /**
3586 | * ### .decreases(function, object, property)
3587 | *
3588 | * Asserts that a function decreases an object property
3589 | *
3590 | * var obj = { val: 10 };
3591 | * var fn = function() { obj.val = 5 };
3592 | * assert.decreases(fn, obj, 'val');
3593 | *
3594 | * @name decreases
3595 | * @param {Function} modifier function
3596 | * @param {Object} object
3597 | * @param {String} property name
3598 | * @param {String} message _optional_
3599 | * @namespace Assert
3600 | * @api public
3601 | */
3602 |
3603 | assert.decreases = function (fn, obj, prop) {
3604 | new Assertion(fn).to.decrease(obj, prop);
3605 | }
3606 |
3607 | /**
3608 | * ### .doesNotDecrease(function, object, property)
3609 | *
3610 | * Asserts that a function does not decreases an object property
3611 | *
3612 | * var obj = { val: 10 };
3613 | * var fn = function() { obj.val = 15 };
3614 | * assert.doesNotDecrease(fn, obj, 'val');
3615 | *
3616 | * @name doesNotDecrease
3617 | * @param {Function} modifier function
3618 | * @param {Object} object
3619 | * @param {String} property name
3620 | * @param {String} message _optional_
3621 | * @namespace Assert
3622 | * @api public
3623 | */
3624 |
3625 | assert.doesNotDecrease = function (fn, obj, prop) {
3626 | new Assertion(fn).to.not.decrease(obj, prop);
3627 | }
3628 |
3629 | /*!
3630 | * ### .ifError(object)
3631 | *
3632 | * Asserts if value is not a false value, and throws if it is a true value.
3633 | * This is added to allow for chai to be a drop-in replacement for Node's
3634 | * assert class.
3635 | *
3636 | * var err = new Error('I am a custom error');
3637 | * assert.ifError(err); // Rethrows err!
3638 | *
3639 | * @name ifError
3640 | * @param {Object} object
3641 | * @namespace Assert
3642 | * @api public
3643 | */
3644 |
3645 | assert.ifError = function (val) {
3646 | if (val) {
3647 | throw(val);
3648 | }
3649 | };
3650 |
3651 | /**
3652 | * ### .isExtensible(object)
3653 | *
3654 | * Asserts that `object` is extensible (can have new properties added to it).
3655 | *
3656 | * assert.isExtensible({});
3657 | *
3658 | * @name isExtensible
3659 | * @alias extensible
3660 | * @param {Object} object
3661 | * @param {String} message _optional_
3662 | * @namespace Assert
3663 | * @api public
3664 | */
3665 |
3666 | assert.isExtensible = function (obj, msg) {
3667 | new Assertion(obj, msg).to.be.extensible;
3668 | };
3669 |
3670 | /**
3671 | * ### .isNotExtensible(object)
3672 | *
3673 | * Asserts that `object` is _not_ extensible.
3674 | *
3675 | * var nonExtensibleObject = Object.preventExtensions({});
3676 | * var sealedObject = Object.seal({});
3677 | * var frozenObject = Object.freese({});
3678 | *
3679 | * assert.isNotExtensible(nonExtensibleObject);
3680 | * assert.isNotExtensible(sealedObject);
3681 | * assert.isNotExtensible(frozenObject);
3682 | *
3683 | * @name isNotExtensible
3684 | * @alias notExtensible
3685 | * @param {Object} object
3686 | * @param {String} message _optional_
3687 | * @namespace Assert
3688 | * @api public
3689 | */
3690 |
3691 | assert.isNotExtensible = function (obj, msg) {
3692 | new Assertion(obj, msg).to.not.be.extensible;
3693 | };
3694 |
3695 | /**
3696 | * ### .isSealed(object)
3697 | *
3698 | * Asserts that `object` is sealed (cannot have new properties added to it
3699 | * and its existing properties cannot be removed).
3700 | *
3701 | * var sealedObject = Object.seal({});
3702 | * var frozenObject = Object.seal({});
3703 | *
3704 | * assert.isSealed(sealedObject);
3705 | * assert.isSealed(frozenObject);
3706 | *
3707 | * @name isSealed
3708 | * @alias sealed
3709 | * @param {Object} object
3710 | * @param {String} message _optional_
3711 | * @namespace Assert
3712 | * @api public
3713 | */
3714 |
3715 | assert.isSealed = function (obj, msg) {
3716 | new Assertion(obj, msg).to.be.sealed;
3717 | };
3718 |
3719 | /**
3720 | * ### .isNotSealed(object)
3721 | *
3722 | * Asserts that `object` is _not_ sealed.
3723 | *
3724 | * assert.isNotSealed({});
3725 | *
3726 | * @name isNotSealed
3727 | * @alias notSealed
3728 | * @param {Object} object
3729 | * @param {String} message _optional_
3730 | * @namespace Assert
3731 | * @api public
3732 | */
3733 |
3734 | assert.isNotSealed = function (obj, msg) {
3735 | new Assertion(obj, msg).to.not.be.sealed;
3736 | };
3737 |
3738 | /**
3739 | * ### .isFrozen(object)
3740 | *
3741 | * Asserts that `object` is frozen (cannot have new properties added to it
3742 | * and its existing properties cannot be modified).
3743 | *
3744 | * var frozenObject = Object.freeze({});
3745 | * assert.frozen(frozenObject);
3746 | *
3747 | * @name isFrozen
3748 | * @alias frozen
3749 | * @param {Object} object
3750 | * @param {String} message _optional_
3751 | * @namespace Assert
3752 | * @api public
3753 | */
3754 |
3755 | assert.isFrozen = function (obj, msg) {
3756 | new Assertion(obj, msg).to.be.frozen;
3757 | };
3758 |
3759 | /**
3760 | * ### .isNotFrozen(object)
3761 | *
3762 | * Asserts that `object` is _not_ frozen.
3763 | *
3764 | * assert.isNotFrozen({});
3765 | *
3766 | * @name isNotFrozen
3767 | * @alias notFrozen
3768 | * @param {Object} object
3769 | * @param {String} message _optional_
3770 | * @namespace Assert
3771 | * @api public
3772 | */
3773 |
3774 | assert.isNotFrozen = function (obj, msg) {
3775 | new Assertion(obj, msg).to.not.be.frozen;
3776 | };
3777 |
3778 | /*!
3779 | * Aliases.
3780 | */
3781 |
3782 | (function alias(name, as){
3783 | assert[as] = assert[name];
3784 | return alias;
3785 | })
3786 | ('isOk', 'ok')
3787 | ('isNotOk', 'notOk')
3788 | ('throws', 'throw')
3789 | ('throws', 'Throw')
3790 | ('isExtensible', 'extensible')
3791 | ('isNotExtensible', 'notExtensible')
3792 | ('isSealed', 'sealed')
3793 | ('isNotSealed', 'notSealed')
3794 | ('isFrozen', 'frozen')
3795 | ('isNotFrozen', 'notFrozen');
3796 | };
3797 |
3798 | },{}],7:[function(require,module,exports){
3799 | /*!
3800 | * chai
3801 | * Copyright(c) 2011-2014 Jake Luer
3802 | * MIT Licensed
3803 | */
3804 |
3805 | module.exports = function (chai, util) {
3806 | chai.expect = function (val, message) {
3807 | return new chai.Assertion(val, message);
3808 | };
3809 |
3810 | /**
3811 | * ### .fail(actual, expected, [message], [operator])
3812 | *
3813 | * Throw a failure.
3814 | *
3815 | * @name fail
3816 | * @param {Mixed} actual
3817 | * @param {Mixed} expected
3818 | * @param {String} message
3819 | * @param {String} operator
3820 | * @namespace Expect
3821 | * @api public
3822 | */
3823 |
3824 | chai.expect.fail = function (actual, expected, message, operator) {
3825 | message = message || 'expect.fail()';
3826 | throw new chai.AssertionError(message, {
3827 | actual: actual
3828 | , expected: expected
3829 | , operator: operator
3830 | }, chai.expect.fail);
3831 | };
3832 | };
3833 |
3834 | },{}],8:[function(require,module,exports){
3835 | /*!
3836 | * chai
3837 | * Copyright(c) 2011-2014 Jake Luer
3838 | * MIT Licensed
3839 | */
3840 |
3841 | module.exports = function (chai, util) {
3842 | var Assertion = chai.Assertion;
3843 |
3844 | function loadShould () {
3845 | // explicitly define this method as function as to have it's name to include as `ssfi`
3846 | function shouldGetter() {
3847 | if (this instanceof String || this instanceof Number || this instanceof Boolean ) {
3848 | return new Assertion(this.valueOf(), null, shouldGetter);
3849 | }
3850 | return new Assertion(this, null, shouldGetter);
3851 | }
3852 | function shouldSetter(value) {
3853 | // See https://github.com/chaijs/chai/issues/86: this makes
3854 | // `whatever.should = someValue` actually set `someValue`, which is
3855 | // especially useful for `global.should = require('chai').should()`.
3856 | //
3857 | // Note that we have to use [[DefineProperty]] instead of [[Put]]
3858 | // since otherwise we would trigger this very setter!
3859 | Object.defineProperty(this, 'should', {
3860 | value: value,
3861 | enumerable: true,
3862 | configurable: true,
3863 | writable: true
3864 | });
3865 | }
3866 | // modify Object.prototype to have `should`
3867 | Object.defineProperty(Object.prototype, 'should', {
3868 | set: shouldSetter
3869 | , get: shouldGetter
3870 | , configurable: true
3871 | });
3872 |
3873 | var should = {};
3874 |
3875 | /**
3876 | * ### .fail(actual, expected, [message], [operator])
3877 | *
3878 | * Throw a failure.
3879 | *
3880 | * @name fail
3881 | * @param {Mixed} actual
3882 | * @param {Mixed} expected
3883 | * @param {String} message
3884 | * @param {String} operator
3885 | * @namespace Should
3886 | * @api public
3887 | */
3888 |
3889 | should.fail = function (actual, expected, message, operator) {
3890 | message = message || 'should.fail()';
3891 | throw new chai.AssertionError(message, {
3892 | actual: actual
3893 | , expected: expected
3894 | , operator: operator
3895 | }, should.fail);
3896 | };
3897 |
3898 | /**
3899 | * ### .equal(actual, expected, [message])
3900 | *
3901 | * Asserts non-strict equality (`==`) of `actual` and `expected`.
3902 | *
3903 | * should.equal(3, '3', '== coerces values to strings');
3904 | *
3905 | * @name equal
3906 | * @param {Mixed} actual
3907 | * @param {Mixed} expected
3908 | * @param {String} message
3909 | * @namespace Should
3910 | * @api public
3911 | */
3912 |
3913 | should.equal = function (val1, val2, msg) {
3914 | new Assertion(val1, msg).to.equal(val2);
3915 | };
3916 |
3917 | /**
3918 | * ### .throw(function, [constructor/string/regexp], [string/regexp], [message])
3919 | *
3920 | * Asserts that `function` will throw an error that is an instance of
3921 | * `constructor`, or alternately that it will throw an error with message
3922 | * matching `regexp`.
3923 | *
3924 | * should.throw(fn, 'function throws a reference error');
3925 | * should.throw(fn, /function throws a reference error/);
3926 | * should.throw(fn, ReferenceError);
3927 | * should.throw(fn, ReferenceError, 'function throws a reference error');
3928 | * should.throw(fn, ReferenceError, /function throws a reference error/);
3929 | *
3930 | * @name throw
3931 | * @alias Throw
3932 | * @param {Function} function
3933 | * @param {ErrorConstructor} constructor
3934 | * @param {RegExp} regexp
3935 | * @param {String} message
3936 | * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
3937 | * @namespace Should
3938 | * @api public
3939 | */
3940 |
3941 | should.Throw = function (fn, errt, errs, msg) {
3942 | new Assertion(fn, msg).to.Throw(errt, errs);
3943 | };
3944 |
3945 | /**
3946 | * ### .exist
3947 | *
3948 | * Asserts that the target is neither `null` nor `undefined`.
3949 | *
3950 | * var foo = 'hi';
3951 | *
3952 | * should.exist(foo, 'foo exists');
3953 | *
3954 | * @name exist
3955 | * @namespace Should
3956 | * @api public
3957 | */
3958 |
3959 | should.exist = function (val, msg) {
3960 | new Assertion(val, msg).to.exist;
3961 | }
3962 |
3963 | // negation
3964 | should.not = {}
3965 |
3966 | /**
3967 | * ### .not.equal(actual, expected, [message])
3968 | *
3969 | * Asserts non-strict inequality (`!=`) of `actual` and `expected`.
3970 | *
3971 | * should.not.equal(3, 4, 'these numbers are not equal');
3972 | *
3973 | * @name not.equal
3974 | * @param {Mixed} actual
3975 | * @param {Mixed} expected
3976 | * @param {String} message
3977 | * @namespace Should
3978 | * @api public
3979 | */
3980 |
3981 | should.not.equal = function (val1, val2, msg) {
3982 | new Assertion(val1, msg).to.not.equal(val2);
3983 | };
3984 |
3985 | /**
3986 | * ### .throw(function, [constructor/regexp], [message])
3987 | *
3988 | * Asserts that `function` will _not_ throw an error that is an instance of
3989 | * `constructor`, or alternately that it will not throw an error with message
3990 | * matching `regexp`.
3991 | *
3992 | * should.not.throw(fn, Error, 'function does not throw');
3993 | *
3994 | * @name not.throw
3995 | * @alias not.Throw
3996 | * @param {Function} function
3997 | * @param {ErrorConstructor} constructor
3998 | * @param {RegExp} regexp
3999 | * @param {String} message
4000 | * @see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error#Error_types
4001 | * @namespace Should
4002 | * @api public
4003 | */
4004 |
4005 | should.not.Throw = function (fn, errt, errs, msg) {
4006 | new Assertion(fn, msg).to.not.Throw(errt, errs);
4007 | };
4008 |
4009 | /**
4010 | * ### .not.exist
4011 | *
4012 | * Asserts that the target is neither `null` nor `undefined`.
4013 | *
4014 | * var bar = null;
4015 | *
4016 | * should.not.exist(bar, 'bar does not exist');
4017 | *
4018 | * @name not.exist
4019 | * @namespace Should
4020 | * @api public
4021 | */
4022 |
4023 | should.not.exist = function (val, msg) {
4024 | new Assertion(val, msg).to.not.exist;
4025 | }
4026 |
4027 | should['throw'] = should['Throw'];
4028 | should.not['throw'] = should.not['Throw'];
4029 |
4030 | return should;
4031 | };
4032 |
4033 | chai.should = loadShould;
4034 | chai.Should = loadShould;
4035 | };
4036 |
4037 | },{}],9:[function(require,module,exports){
4038 | /*!
4039 | * Chai - addChainingMethod utility
4040 | * Copyright(c) 2012-2014 Jake Luer
4041 | * MIT Licensed
4042 | */
4043 |
4044 | /*!
4045 | * Module dependencies
4046 | */
4047 |
4048 | var transferFlags = require('./transferFlags');
4049 | var flag = require('./flag');
4050 | var config = require('../config');
4051 |
4052 | /*!
4053 | * Module variables
4054 | */
4055 |
4056 | // Check whether `__proto__` is supported
4057 | var hasProtoSupport = '__proto__' in Object;
4058 |
4059 | // Without `__proto__` support, this module will need to add properties to a function.
4060 | // However, some Function.prototype methods cannot be overwritten,
4061 | // and there seems no easy cross-platform way to detect them (@see chaijs/chai/issues/69).
4062 | var excludeNames = /^(?:length|name|arguments|caller)$/;
4063 |
4064 | // Cache `Function` properties
4065 | var call = Function.prototype.call,
4066 | apply = Function.prototype.apply;
4067 |
4068 | /**
4069 | * ### addChainableMethod (ctx, name, method, chainingBehavior)
4070 | *
4071 | * Adds a method to an object, such that the method can also be chained.
4072 | *
4073 | * utils.addChainableMethod(chai.Assertion.prototype, 'foo', function (str) {
4074 | * var obj = utils.flag(this, 'object');
4075 | * new chai.Assertion(obj).to.be.equal(str);
4076 | * });
4077 | *
4078 | * Can also be accessed directly from `chai.Assertion`.
4079 | *
4080 | * chai.Assertion.addChainableMethod('foo', fn, chainingBehavior);
4081 | *
4082 | * The result can then be used as both a method assertion, executing both `method` and
4083 | * `chainingBehavior`, or as a language chain, which only executes `chainingBehavior`.
4084 | *
4085 | * expect(fooStr).to.be.foo('bar');
4086 | * expect(fooStr).to.be.foo.equal('foo');
4087 | *
4088 | * @param {Object} ctx object to which the method is added
4089 | * @param {String} name of method to add
4090 | * @param {Function} method function to be used for `name`, when called
4091 | * @param {Function} chainingBehavior function to be called every time the property is accessed
4092 | * @namespace Utils
4093 | * @name addChainableMethod
4094 | * @api public
4095 | */
4096 |
4097 | module.exports = function (ctx, name, method, chainingBehavior) {
4098 | if (typeof chainingBehavior !== 'function') {
4099 | chainingBehavior = function () { };
4100 | }
4101 |
4102 | var chainableBehavior = {
4103 | method: method
4104 | , chainingBehavior: chainingBehavior
4105 | };
4106 |
4107 | // save the methods so we can overwrite them later, if we need to.
4108 | if (!ctx.__methods) {
4109 | ctx.__methods = {};
4110 | }
4111 | ctx.__methods[name] = chainableBehavior;
4112 |
4113 | Object.defineProperty(ctx, name,
4114 | { get: function () {
4115 | chainableBehavior.chainingBehavior.call(this);
4116 |
4117 | var assert = function assert() {
4118 | var old_ssfi = flag(this, 'ssfi');
4119 | if (old_ssfi && config.includeStack === false)
4120 | flag(this, 'ssfi', assert);
4121 | var result = chainableBehavior.method.apply(this, arguments);
4122 | return result === undefined ? this : result;
4123 | };
4124 |
4125 | // Use `__proto__` if available
4126 | if (hasProtoSupport) {
4127 | // Inherit all properties from the object by replacing the `Function` prototype
4128 | var prototype = assert.__proto__ = Object.create(this);
4129 | // Restore the `call` and `apply` methods from `Function`
4130 | prototype.call = call;
4131 | prototype.apply = apply;
4132 | }
4133 | // Otherwise, redefine all properties (slow!)
4134 | else {
4135 | var asserterNames = Object.getOwnPropertyNames(ctx);
4136 | asserterNames.forEach(function (asserterName) {
4137 | if (!excludeNames.test(asserterName)) {
4138 | var pd = Object.getOwnPropertyDescriptor(ctx, asserterName);
4139 | Object.defineProperty(assert, asserterName, pd);
4140 | }
4141 | });
4142 | }
4143 |
4144 | transferFlags(this, assert);
4145 | return assert;
4146 | }
4147 | , configurable: true
4148 | });
4149 | };
4150 |
4151 | },{"../config":4,"./flag":13,"./transferFlags":29}],10:[function(require,module,exports){
4152 | /*!
4153 | * Chai - addMethod utility
4154 | * Copyright(c) 2012-2014 Jake Luer
4155 | * MIT Licensed
4156 | */
4157 |
4158 | var config = require('../config');
4159 |
4160 | /**
4161 | * ### .addMethod (ctx, name, method)
4162 | *
4163 | * Adds a method to the prototype of an object.
4164 | *
4165 | * utils.addMethod(chai.Assertion.prototype, 'foo', function (str) {
4166 | * var obj = utils.flag(this, 'object');
4167 | * new chai.Assertion(obj).to.be.equal(str);
4168 | * });
4169 | *
4170 | * Can also be accessed directly from `chai.Assertion`.
4171 | *
4172 | * chai.Assertion.addMethod('foo', fn);
4173 | *
4174 | * Then can be used as any other assertion.
4175 | *
4176 | * expect(fooStr).to.be.foo('bar');
4177 | *
4178 | * @param {Object} ctx object to which the method is added
4179 | * @param {String} name of method to add
4180 | * @param {Function} method function to be used for name
4181 | * @namespace Utils
4182 | * @name addMethod
4183 | * @api public
4184 | */
4185 | var flag = require('./flag');
4186 |
4187 | module.exports = function (ctx, name, method) {
4188 | ctx[name] = function () {
4189 | var old_ssfi = flag(this, 'ssfi');
4190 | if (old_ssfi && config.includeStack === false)
4191 | flag(this, 'ssfi', ctx[name]);
4192 | var result = method.apply(this, arguments);
4193 | return result === undefined ? this : result;
4194 | };
4195 | };
4196 |
4197 | },{"../config":4,"./flag":13}],11:[function(require,module,exports){
4198 | /*!
4199 | * Chai - addProperty utility
4200 | * Copyright(c) 2012-2014 Jake Luer
4201 | * MIT Licensed
4202 | */
4203 |
4204 | var config = require('../config');
4205 | var flag = require('./flag');
4206 |
4207 | /**
4208 | * ### addProperty (ctx, name, getter)
4209 | *
4210 | * Adds a property to the prototype of an object.
4211 | *
4212 | * utils.addProperty(chai.Assertion.prototype, 'foo', function () {
4213 | * var obj = utils.flag(this, 'object');
4214 | * new chai.Assertion(obj).to.be.instanceof(Foo);
4215 | * });
4216 | *
4217 | * Can also be accessed directly from `chai.Assertion`.
4218 | *
4219 | * chai.Assertion.addProperty('foo', fn);
4220 | *
4221 | * Then can be used as any other assertion.
4222 | *
4223 | * expect(myFoo).to.be.foo;
4224 | *
4225 | * @param {Object} ctx object to which the property is added
4226 | * @param {String} name of property to add
4227 | * @param {Function} getter function to be used for name
4228 | * @namespace Utils
4229 | * @name addProperty
4230 | * @api public
4231 | */
4232 |
4233 | module.exports = function (ctx, name, getter) {
4234 | Object.defineProperty(ctx, name,
4235 | { get: function addProperty() {
4236 | var old_ssfi = flag(this, 'ssfi');
4237 | if (old_ssfi && config.includeStack === false)
4238 | flag(this, 'ssfi', addProperty);
4239 |
4240 | var result = getter.call(this);
4241 | return result === undefined ? this : result;
4242 | }
4243 | , configurable: true
4244 | });
4245 | };
4246 |
4247 | },{"../config":4,"./flag":13}],12:[function(require,module,exports){
4248 | /*!
4249 | * Chai - expectTypes utility
4250 | * Copyright(c) 2012-2014 Jake Luer
4251 | * MIT Licensed
4252 | */
4253 |
4254 | /**
4255 | * ### expectTypes(obj, types)
4256 | *
4257 | * Ensures that the object being tested against is of a valid type.
4258 | *
4259 | * utils.expectTypes(this, ['array', 'object', 'string']);
4260 | *
4261 | * @param {Mixed} obj constructed Assertion
4262 | * @param {Array} type A list of allowed types for this assertion
4263 | * @namespace Utils
4264 | * @name expectTypes
4265 | * @api public
4266 | */
4267 |
4268 | var AssertionError = require('assertion-error');
4269 | var flag = require('./flag');
4270 | var type = require('type-detect');
4271 |
4272 | module.exports = function (obj, types) {
4273 | var obj = flag(obj, 'object');
4274 | types = types.map(function (t) { return t.toLowerCase(); });
4275 | types.sort();
4276 |
4277 | // Transforms ['lorem', 'ipsum'] into 'a lirum, or an ipsum'
4278 | var str = types.map(function (t, index) {
4279 | var art = ~[ 'a', 'e', 'i', 'o', 'u' ].indexOf(t.charAt(0)) ? 'an' : 'a';
4280 | var or = types.length > 1 && index === types.length - 1 ? 'or ' : '';
4281 | return or + art + ' ' + t;
4282 | }).join(', ');
4283 |
4284 | if (!types.some(function (expected) { return type(obj) === expected; })) {
4285 | throw new AssertionError(
4286 | 'object tested must be ' + str + ', but ' + type(obj) + ' given'
4287 | );
4288 | }
4289 | };
4290 |
4291 | },{"./flag":13,"assertion-error":30,"type-detect":35}],13:[function(require,module,exports){
4292 | /*!
4293 | * Chai - flag utility
4294 | * Copyright(c) 2012-2014 Jake Luer
4295 | * MIT Licensed
4296 | */
4297 |
4298 | /**
4299 | * ### flag(object, key, [value])
4300 | *
4301 | * Get or set a flag value on an object. If a
4302 | * value is provided it will be set, else it will
4303 | * return the currently set value or `undefined` if
4304 | * the value is not set.
4305 | *
4306 | * utils.flag(this, 'foo', 'bar'); // setter
4307 | * utils.flag(this, 'foo'); // getter, returns `bar`
4308 | *
4309 | * @param {Object} object constructed Assertion
4310 | * @param {String} key
4311 | * @param {Mixed} value (optional)
4312 | * @namespace Utils
4313 | * @name flag
4314 | * @api private
4315 | */
4316 |
4317 | module.exports = function (obj, key, value) {
4318 | var flags = obj.__flags || (obj.__flags = Object.create(null));
4319 | if (arguments.length === 3) {
4320 | flags[key] = value;
4321 | } else {
4322 | return flags[key];
4323 | }
4324 | };
4325 |
4326 | },{}],14:[function(require,module,exports){
4327 | /*!
4328 | * Chai - getActual utility
4329 | * Copyright(c) 2012-2014 Jake Luer
4330 | * MIT Licensed
4331 | */
4332 |
4333 | /**
4334 | * # getActual(object, [actual])
4335 | *
4336 | * Returns the `actual` value for an Assertion
4337 | *
4338 | * @param {Object} object (constructed Assertion)
4339 | * @param {Arguments} chai.Assertion.prototype.assert arguments
4340 | * @namespace Utils
4341 | * @name getActual
4342 | */
4343 |
4344 | module.exports = function (obj, args) {
4345 | return args.length > 4 ? args[4] : obj._obj;
4346 | };
4347 |
4348 | },{}],15:[function(require,module,exports){
4349 | /*!
4350 | * Chai - getEnumerableProperties utility
4351 | * Copyright(c) 2012-2014 Jake Luer
4352 | * MIT Licensed
4353 | */
4354 |
4355 | /**
4356 | * ### .getEnumerableProperties(object)
4357 | *
4358 | * This allows the retrieval of enumerable property names of an object,
4359 | * inherited or not.
4360 | *
4361 | * @param {Object} object
4362 | * @returns {Array}
4363 | * @namespace Utils
4364 | * @name getEnumerableProperties
4365 | * @api public
4366 | */
4367 |
4368 | module.exports = function getEnumerableProperties(object) {
4369 | var result = [];
4370 | for (var name in object) {
4371 | result.push(name);
4372 | }
4373 | return result;
4374 | };
4375 |
4376 | },{}],16:[function(require,module,exports){
4377 | /*!
4378 | * Chai - message composition utility
4379 | * Copyright(c) 2012-2014 Jake Luer
4380 | * MIT Licensed
4381 | */
4382 |
4383 | /*!
4384 | * Module dependancies
4385 | */
4386 |
4387 | var flag = require('./flag')
4388 | , getActual = require('./getActual')
4389 | , inspect = require('./inspect')
4390 | , objDisplay = require('./objDisplay');
4391 |
4392 | /**
4393 | * ### .getMessage(object, message, negateMessage)
4394 | *
4395 | * Construct the error message based on flags
4396 | * and template tags. Template tags will return
4397 | * a stringified inspection of the object referenced.
4398 | *
4399 | * Message template tags:
4400 | * - `#{this}` current asserted object
4401 | * - `#{act}` actual value
4402 | * - `#{exp}` expected value
4403 | *
4404 | * @param {Object} object (constructed Assertion)
4405 | * @param {Arguments} chai.Assertion.prototype.assert arguments
4406 | * @namespace Utils
4407 | * @name getMessage
4408 | * @api public
4409 | */
4410 |
4411 | module.exports = function (obj, args) {
4412 | var negate = flag(obj, 'negate')
4413 | , val = flag(obj, 'object')
4414 | , expected = args[3]
4415 | , actual = getActual(obj, args)
4416 | , msg = negate ? args[2] : args[1]
4417 | , flagMsg = flag(obj, 'message');
4418 |
4419 | if(typeof msg === "function") msg = msg();
4420 | msg = msg || '';
4421 | msg = msg
4422 | .replace(/#\{this\}/g, function () { return objDisplay(val); })
4423 | .replace(/#\{act\}/g, function () { return objDisplay(actual); })
4424 | .replace(/#\{exp\}/g, function () { return objDisplay(expected); });
4425 |
4426 | return flagMsg ? flagMsg + ': ' + msg : msg;
4427 | };
4428 |
4429 | },{"./flag":13,"./getActual":14,"./inspect":23,"./objDisplay":24}],17:[function(require,module,exports){
4430 | /*!
4431 | * Chai - getName utility
4432 | * Copyright(c) 2012-2014 Jake Luer
4433 | * MIT Licensed
4434 | */
4435 |
4436 | /**
4437 | * # getName(func)
4438 | *
4439 | * Gets the name of a function, in a cross-browser way.
4440 | *
4441 | * @param {Function} a function (usually a constructor)
4442 | * @namespace Utils
4443 | * @name getName
4444 | */
4445 |
4446 | module.exports = function (func) {
4447 | if (func.name) return func.name;
4448 |
4449 | var match = /^\s?function ([^(]*)\(/.exec(func);
4450 | return match && match[1] ? match[1] : "";
4451 | };
4452 |
4453 | },{}],18:[function(require,module,exports){
4454 | /*!
4455 | * Chai - getPathInfo utility
4456 | * Copyright(c) 2012-2014 Jake Luer
4457 | * MIT Licensed
4458 | */
4459 |
4460 | var hasProperty = require('./hasProperty');
4461 |
4462 | /**
4463 | * ### .getPathInfo(path, object)
4464 | *
4465 | * This allows the retrieval of property info in an
4466 | * object given a string path.
4467 | *
4468 | * The path info consists of an object with the
4469 | * following properties:
4470 | *
4471 | * * parent - The parent object of the property referenced by `path`
4472 | * * name - The name of the final property, a number if it was an array indexer
4473 | * * value - The value of the property, if it exists, otherwise `undefined`
4474 | * * exists - Whether the property exists or not
4475 | *
4476 | * @param {String} path
4477 | * @param {Object} object
4478 | * @returns {Object} info
4479 | * @namespace Utils
4480 | * @name getPathInfo
4481 | * @api public
4482 | */
4483 |
4484 | module.exports = function getPathInfo(path, obj) {
4485 | var parsed = parsePath(path),
4486 | last = parsed[parsed.length - 1];
4487 |
4488 | var info = {
4489 | parent: parsed.length > 1 ? _getPathValue(parsed, obj, parsed.length - 1) : obj,
4490 | name: last.p || last.i,
4491 | value: _getPathValue(parsed, obj)
4492 | };
4493 | info.exists = hasProperty(info.name, info.parent);
4494 |
4495 | return info;
4496 | };
4497 |
4498 |
4499 | /*!
4500 | * ## parsePath(path)
4501 | *
4502 | * Helper function used to parse string object
4503 | * paths. Use in conjunction with `_getPathValue`.
4504 | *
4505 | * var parsed = parsePath('myobject.property.subprop');
4506 | *
4507 | * ### Paths:
4508 | *
4509 | * * Can be as near infinitely deep and nested
4510 | * * Arrays are also valid using the formal `myobject.document[3].property`.
4511 | * * Literal dots and brackets (not delimiter) must be backslash-escaped.
4512 | *
4513 | * @param {String} path
4514 | * @returns {Object} parsed
4515 | * @api private
4516 | */
4517 |
4518 | function parsePath (path) {
4519 | var str = path.replace(/([^\\])\[/g, '$1.[')
4520 | , parts = str.match(/(\\\.|[^.]+?)+/g);
4521 | return parts.map(function (value) {
4522 | var re = /^\[(\d+)\]$/
4523 | , mArr = re.exec(value);
4524 | if (mArr) return { i: parseFloat(mArr[1]) };
4525 | else return { p: value.replace(/\\([.\[\]])/g, '$1') };
4526 | });
4527 | }
4528 |
4529 |
4530 | /*!
4531 | * ## _getPathValue(parsed, obj)
4532 | *
4533 | * Helper companion function for `.parsePath` that returns
4534 | * the value located at the parsed address.
4535 | *
4536 | * var value = getPathValue(parsed, obj);
4537 | *
4538 | * @param {Object} parsed definition from `parsePath`.
4539 | * @param {Object} object to search against
4540 | * @param {Number} object to search against
4541 | * @returns {Object|Undefined} value
4542 | * @api private
4543 | */
4544 |
4545 | function _getPathValue (parsed, obj, index) {
4546 | var tmp = obj
4547 | , res;
4548 |
4549 | index = (index === undefined ? parsed.length : index);
4550 |
4551 | for (var i = 0, l = index; i < l; i++) {
4552 | var part = parsed[i];
4553 | if (tmp) {
4554 | if ('undefined' !== typeof part.p)
4555 | tmp = tmp[part.p];
4556 | else if ('undefined' !== typeof part.i)
4557 | tmp = tmp[part.i];
4558 | if (i == (l - 1)) res = tmp;
4559 | } else {
4560 | res = undefined;
4561 | }
4562 | }
4563 | return res;
4564 | }
4565 |
4566 | },{"./hasProperty":21}],19:[function(require,module,exports){
4567 | /*!
4568 | * Chai - getPathValue utility
4569 | * Copyright(c) 2012-2014 Jake Luer
4570 | * @see https://github.com/logicalparadox/filtr
4571 | * MIT Licensed
4572 | */
4573 |
4574 | var getPathInfo = require('./getPathInfo');
4575 |
4576 | /**
4577 | * ### .getPathValue(path, object)
4578 | *
4579 | * This allows the retrieval of values in an
4580 | * object given a string path.
4581 | *
4582 | * var obj = {
4583 | * prop1: {
4584 | * arr: ['a', 'b', 'c']
4585 | * , str: 'Hello'
4586 | * }
4587 | * , prop2: {
4588 | * arr: [ { nested: 'Universe' } ]
4589 | * , str: 'Hello again!'
4590 | * }
4591 | * }
4592 | *
4593 | * The following would be the results.
4594 | *
4595 | * getPathValue('prop1.str', obj); // Hello
4596 | * getPathValue('prop1.att[2]', obj); // b
4597 | * getPathValue('prop2.arr[0].nested', obj); // Universe
4598 | *
4599 | * @param {String} path
4600 | * @param {Object} object
4601 | * @returns {Object} value or `undefined`
4602 | * @namespace Utils
4603 | * @name getPathValue
4604 | * @api public
4605 | */
4606 | module.exports = function(path, obj) {
4607 | var info = getPathInfo(path, obj);
4608 | return info.value;
4609 | };
4610 |
4611 | },{"./getPathInfo":18}],20:[function(require,module,exports){
4612 | /*!
4613 | * Chai - getProperties utility
4614 | * Copyright(c) 2012-2014 Jake Luer
4615 | * MIT Licensed
4616 | */
4617 |
4618 | /**
4619 | * ### .getProperties(object)
4620 | *
4621 | * This allows the retrieval of property names of an object, enumerable or not,
4622 | * inherited or not.
4623 | *
4624 | * @param {Object} object
4625 | * @returns {Array}
4626 | * @namespace Utils
4627 | * @name getProperties
4628 | * @api public
4629 | */
4630 |
4631 | module.exports = function getProperties(object) {
4632 | var result = Object.getOwnPropertyNames(object);
4633 |
4634 | function addProperty(property) {
4635 | if (result.indexOf(property) === -1) {
4636 | result.push(property);
4637 | }
4638 | }
4639 |
4640 | var proto = Object.getPrototypeOf(object);
4641 | while (proto !== null) {
4642 | Object.getOwnPropertyNames(proto).forEach(addProperty);
4643 | proto = Object.getPrototypeOf(proto);
4644 | }
4645 |
4646 | return result;
4647 | };
4648 |
4649 | },{}],21:[function(require,module,exports){
4650 | /*!
4651 | * Chai - hasProperty utility
4652 | * Copyright(c) 2012-2014 Jake Luer
4653 | * MIT Licensed
4654 | */
4655 |
4656 | var type = require('type-detect');
4657 |
4658 | /**
4659 | * ### .hasProperty(object, name)
4660 | *
4661 | * This allows checking whether an object has
4662 | * named property or numeric array index.
4663 | *
4664 | * Basically does the same thing as the `in`
4665 | * operator but works properly with natives
4666 | * and null/undefined values.
4667 | *
4668 | * var obj = {
4669 | * arr: ['a', 'b', 'c']
4670 | * , str: 'Hello'
4671 | * }
4672 | *
4673 | * The following would be the results.
4674 | *
4675 | * hasProperty('str', obj); // true
4676 | * hasProperty('constructor', obj); // true
4677 | * hasProperty('bar', obj); // false
4678 | *
4679 | * hasProperty('length', obj.str); // true
4680 | * hasProperty(1, obj.str); // true
4681 | * hasProperty(5, obj.str); // false
4682 | *
4683 | * hasProperty('length', obj.arr); // true
4684 | * hasProperty(2, obj.arr); // true
4685 | * hasProperty(3, obj.arr); // false
4686 | *
4687 | * @param {Objuect} object
4688 | * @param {String|Number} name
4689 | * @returns {Boolean} whether it exists
4690 | * @namespace Utils
4691 | * @name getPathInfo
4692 | * @api public
4693 | */
4694 |
4695 | var literals = {
4696 | 'number': Number
4697 | , 'string': String
4698 | };
4699 |
4700 | module.exports = function hasProperty(name, obj) {
4701 | var ot = type(obj);
4702 |
4703 | // Bad Object, obviously no props at all
4704 | if(ot === 'null' || ot === 'undefined')
4705 | return false;
4706 |
4707 | // The `in` operator does not work with certain literals
4708 | // box these before the check
4709 | if(literals[ot] && typeof obj !== 'object')
4710 | obj = new literals[ot](obj);
4711 |
4712 | return name in obj;
4713 | };
4714 |
4715 | },{"type-detect":35}],22:[function(require,module,exports){
4716 | /*!
4717 | * chai
4718 | * Copyright(c) 2011 Jake Luer
4719 | * MIT Licensed
4720 | */
4721 |
4722 | /*!
4723 | * Main exports
4724 | */
4725 |
4726 | var exports = module.exports = {};
4727 |
4728 | /*!
4729 | * test utility
4730 | */
4731 |
4732 | exports.test = require('./test');
4733 |
4734 | /*!
4735 | * type utility
4736 | */
4737 |
4738 | exports.type = require('type-detect');
4739 |
4740 | /*!
4741 | * expectTypes utility
4742 | */
4743 | exports.expectTypes = require('./expectTypes');
4744 |
4745 | /*!
4746 | * message utility
4747 | */
4748 |
4749 | exports.getMessage = require('./getMessage');
4750 |
4751 | /*!
4752 | * actual utility
4753 | */
4754 |
4755 | exports.getActual = require('./getActual');
4756 |
4757 | /*!
4758 | * Inspect util
4759 | */
4760 |
4761 | exports.inspect = require('./inspect');
4762 |
4763 | /*!
4764 | * Object Display util
4765 | */
4766 |
4767 | exports.objDisplay = require('./objDisplay');
4768 |
4769 | /*!
4770 | * Flag utility
4771 | */
4772 |
4773 | exports.flag = require('./flag');
4774 |
4775 | /*!
4776 | * Flag transferring utility
4777 | */
4778 |
4779 | exports.transferFlags = require('./transferFlags');
4780 |
4781 | /*!
4782 | * Deep equal utility
4783 | */
4784 |
4785 | exports.eql = require('deep-eql');
4786 |
4787 | /*!
4788 | * Deep path value
4789 | */
4790 |
4791 | exports.getPathValue = require('./getPathValue');
4792 |
4793 | /*!
4794 | * Deep path info
4795 | */
4796 |
4797 | exports.getPathInfo = require('./getPathInfo');
4798 |
4799 | /*!
4800 | * Check if a property exists
4801 | */
4802 |
4803 | exports.hasProperty = require('./hasProperty');
4804 |
4805 | /*!
4806 | * Function name
4807 | */
4808 |
4809 | exports.getName = require('./getName');
4810 |
4811 | /*!
4812 | * add Property
4813 | */
4814 |
4815 | exports.addProperty = require('./addProperty');
4816 |
4817 | /*!
4818 | * add Method
4819 | */
4820 |
4821 | exports.addMethod = require('./addMethod');
4822 |
4823 | /*!
4824 | * overwrite Property
4825 | */
4826 |
4827 | exports.overwriteProperty = require('./overwriteProperty');
4828 |
4829 | /*!
4830 | * overwrite Method
4831 | */
4832 |
4833 | exports.overwriteMethod = require('./overwriteMethod');
4834 |
4835 | /*!
4836 | * Add a chainable method
4837 | */
4838 |
4839 | exports.addChainableMethod = require('./addChainableMethod');
4840 |
4841 | /*!
4842 | * Overwrite chainable method
4843 | */
4844 |
4845 | exports.overwriteChainableMethod = require('./overwriteChainableMethod');
4846 |
4847 | },{"./addChainableMethod":9,"./addMethod":10,"./addProperty":11,"./expectTypes":12,"./flag":13,"./getActual":14,"./getMessage":16,"./getName":17,"./getPathInfo":18,"./getPathValue":19,"./hasProperty":21,"./inspect":23,"./objDisplay":24,"./overwriteChainableMethod":25,"./overwriteMethod":26,"./overwriteProperty":27,"./test":28,"./transferFlags":29,"deep-eql":31,"type-detect":35}],23:[function(require,module,exports){
4848 | // This is (almost) directly from Node.js utils
4849 | // https://github.com/joyent/node/blob/f8c335d0caf47f16d31413f89aa28eda3878e3aa/lib/util.js
4850 |
4851 | var getName = require('./getName');
4852 | var getProperties = require('./getProperties');
4853 | var getEnumerableProperties = require('./getEnumerableProperties');
4854 |
4855 | module.exports = inspect;
4856 |
4857 | /**
4858 | * Echos the value of a value. Trys to print the value out
4859 | * in the best way possible given the different types.
4860 | *
4861 | * @param {Object} obj The object to print out.
4862 | * @param {Boolean} showHidden Flag that shows hidden (not enumerable)
4863 | * properties of objects.
4864 | * @param {Number} depth Depth in which to descend in object. Default is 2.
4865 | * @param {Boolean} colors Flag to turn on ANSI escape codes to color the
4866 | * output. Default is false (no coloring).
4867 | * @namespace Utils
4868 | * @name inspect
4869 | */
4870 | function inspect(obj, showHidden, depth, colors) {
4871 | var ctx = {
4872 | showHidden: showHidden,
4873 | seen: [],
4874 | stylize: function (str) { return str; }
4875 | };
4876 | return formatValue(ctx, obj, (typeof depth === 'undefined' ? 2 : depth));
4877 | }
4878 |
4879 | // Returns true if object is a DOM element.
4880 | var isDOMElement = function (object) {
4881 | if (typeof HTMLElement === 'object') {
4882 | return object instanceof HTMLElement;
4883 | } else {
4884 | return object &&
4885 | typeof object === 'object' &&
4886 | object.nodeType === 1 &&
4887 | typeof object.nodeName === 'string';
4888 | }
4889 | };
4890 |
4891 | function formatValue(ctx, value, recurseTimes) {
4892 | // Provide a hook for user-specified inspect functions.
4893 | // Check that value is an object with an inspect function on it
4894 | if (value && typeof value.inspect === 'function' &&
4895 | // Filter out the util module, it's inspect function is special
4896 | value.inspect !== exports.inspect &&
4897 | // Also filter out any prototype objects using the circular check.
4898 | !(value.constructor && value.constructor.prototype === value)) {
4899 | var ret = value.inspect(recurseTimes);
4900 | if (typeof ret !== 'string') {
4901 | ret = formatValue(ctx, ret, recurseTimes);
4902 | }
4903 | return ret;
4904 | }
4905 |
4906 | // Primitive types cannot have properties
4907 | var primitive = formatPrimitive(ctx, value);
4908 | if (primitive) {
4909 | return primitive;
4910 | }
4911 |
4912 | // If this is a DOM element, try to get the outer HTML.
4913 | if (isDOMElement(value)) {
4914 | if ('outerHTML' in value) {
4915 | return value.outerHTML;
4916 | // This value does not have an outerHTML attribute,
4917 | // it could still be an XML element
4918 | } else {
4919 | // Attempt to serialize it
4920 | try {
4921 | if (document.xmlVersion) {
4922 | var xmlSerializer = new XMLSerializer();
4923 | return xmlSerializer.serializeToString(value);
4924 | } else {
4925 | // Firefox 11- do not support outerHTML
4926 | // It does, however, support innerHTML
4927 | // Use the following to render the element
4928 | var ns = "http://www.w3.org/1999/xhtml";
4929 | var container = document.createElementNS(ns, '_');
4930 |
4931 | container.appendChild(value.cloneNode(false));
4932 | html = container.innerHTML
4933 | .replace('><', '>' + value.innerHTML + '<');
4934 | container.innerHTML = '';
4935 | return html;
4936 | }
4937 | } catch (err) {
4938 | // This could be a non-native DOM implementation,
4939 | // continue with the normal flow:
4940 | // printing the element as if it is an object.
4941 | }
4942 | }
4943 | }
4944 |
4945 | // Look up the keys of the object.
4946 | var visibleKeys = getEnumerableProperties(value);
4947 | var keys = ctx.showHidden ? getProperties(value) : visibleKeys;
4948 |
4949 | // Some type of object without properties can be shortcutted.
4950 | // In IE, errors have a single `stack` property, or if they are vanilla `Error`,
4951 | // a `stack` plus `description` property; ignore those for consistency.
4952 | if (keys.length === 0 || (isError(value) && (
4953 | (keys.length === 1 && keys[0] === 'stack') ||
4954 | (keys.length === 2 && keys[0] === 'description' && keys[1] === 'stack')
4955 | ))) {
4956 | if (typeof value === 'function') {
4957 | var name = getName(value);
4958 | var nameSuffix = name ? ': ' + name : '';
4959 | return ctx.stylize('[Function' + nameSuffix + ']', 'special');
4960 | }
4961 | if (isRegExp(value)) {
4962 | return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
4963 | }
4964 | if (isDate(value)) {
4965 | return ctx.stylize(Date.prototype.toUTCString.call(value), 'date');
4966 | }
4967 | if (isError(value)) {
4968 | return formatError(value);
4969 | }
4970 | }
4971 |
4972 | var base = '', array = false, braces = ['{', '}'];
4973 |
4974 | // Make Array say that they are Array
4975 | if (isArray(value)) {
4976 | array = true;
4977 | braces = ['[', ']'];
4978 | }
4979 |
4980 | // Make functions say that they are functions
4981 | if (typeof value === 'function') {
4982 | var name = getName(value);
4983 | var nameSuffix = name ? ': ' + name : '';
4984 | base = ' [Function' + nameSuffix + ']';
4985 | }
4986 |
4987 | // Make RegExps say that they are RegExps
4988 | if (isRegExp(value)) {
4989 | base = ' ' + RegExp.prototype.toString.call(value);
4990 | }
4991 |
4992 | // Make dates with properties first say the date
4993 | if (isDate(value)) {
4994 | base = ' ' + Date.prototype.toUTCString.call(value);
4995 | }
4996 |
4997 | // Make error with message first say the error
4998 | if (isError(value)) {
4999 | return formatError(value);
5000 | }
5001 |
5002 | if (keys.length === 0 && (!array || value.length == 0)) {
5003 | return braces[0] + base + braces[1];
5004 | }
5005 |
5006 | if (recurseTimes < 0) {
5007 | if (isRegExp(value)) {
5008 | return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp');
5009 | } else {
5010 | return ctx.stylize('[Object]', 'special');
5011 | }
5012 | }
5013 |
5014 | ctx.seen.push(value);
5015 |
5016 | var output;
5017 | if (array) {
5018 | output = formatArray(ctx, value, recurseTimes, visibleKeys, keys);
5019 | } else {
5020 | output = keys.map(function(key) {
5021 | return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array);
5022 | });
5023 | }
5024 |
5025 | ctx.seen.pop();
5026 |
5027 | return reduceToSingleString(output, base, braces);
5028 | }
5029 |
5030 |
5031 | function formatPrimitive(ctx, value) {
5032 | switch (typeof value) {
5033 | case 'undefined':
5034 | return ctx.stylize('undefined', 'undefined');
5035 |
5036 | case 'string':
5037 | var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '')
5038 | .replace(/'/g, "\\'")
5039 | .replace(/\\"/g, '"') + '\'';
5040 | return ctx.stylize(simple, 'string');
5041 |
5042 | case 'number':
5043 | if (value === 0 && (1/value) === -Infinity) {
5044 | return ctx.stylize('-0', 'number');
5045 | }
5046 | return ctx.stylize('' + value, 'number');
5047 |
5048 | case 'boolean':
5049 | return ctx.stylize('' + value, 'boolean');
5050 | }
5051 | // For some reason typeof null is "object", so special case here.
5052 | if (value === null) {
5053 | return ctx.stylize('null', 'null');
5054 | }
5055 | }
5056 |
5057 |
5058 | function formatError(value) {
5059 | return '[' + Error.prototype.toString.call(value) + ']';
5060 | }
5061 |
5062 |
5063 | function formatArray(ctx, value, recurseTimes, visibleKeys, keys) {
5064 | var output = [];
5065 | for (var i = 0, l = value.length; i < l; ++i) {
5066 | if (Object.prototype.hasOwnProperty.call(value, String(i))) {
5067 | output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
5068 | String(i), true));
5069 | } else {
5070 | output.push('');
5071 | }
5072 | }
5073 | keys.forEach(function(key) {
5074 | if (!key.match(/^\d+$/)) {
5075 | output.push(formatProperty(ctx, value, recurseTimes, visibleKeys,
5076 | key, true));
5077 | }
5078 | });
5079 | return output;
5080 | }
5081 |
5082 |
5083 | function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) {
5084 | var name, str;
5085 | if (value.__lookupGetter__) {
5086 | if (value.__lookupGetter__(key)) {
5087 | if (value.__lookupSetter__(key)) {
5088 | str = ctx.stylize('[Getter/Setter]', 'special');
5089 | } else {
5090 | str = ctx.stylize('[Getter]', 'special');
5091 | }
5092 | } else {
5093 | if (value.__lookupSetter__(key)) {
5094 | str = ctx.stylize('[Setter]', 'special');
5095 | }
5096 | }
5097 | }
5098 | if (visibleKeys.indexOf(key) < 0) {
5099 | name = '[' + key + ']';
5100 | }
5101 | if (!str) {
5102 | if (ctx.seen.indexOf(value[key]) < 0) {
5103 | if (recurseTimes === null) {
5104 | str = formatValue(ctx, value[key], null);
5105 | } else {
5106 | str = formatValue(ctx, value[key], recurseTimes - 1);
5107 | }
5108 | if (str.indexOf('\n') > -1) {
5109 | if (array) {
5110 | str = str.split('\n').map(function(line) {
5111 | return ' ' + line;
5112 | }).join('\n').substr(2);
5113 | } else {
5114 | str = '\n' + str.split('\n').map(function(line) {
5115 | return ' ' + line;
5116 | }).join('\n');
5117 | }
5118 | }
5119 | } else {
5120 | str = ctx.stylize('[Circular]', 'special');
5121 | }
5122 | }
5123 | if (typeof name === 'undefined') {
5124 | if (array && key.match(/^\d+$/)) {
5125 | return str;
5126 | }
5127 | name = JSON.stringify('' + key);
5128 | if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) {
5129 | name = name.substr(1, name.length - 2);
5130 | name = ctx.stylize(name, 'name');
5131 | } else {
5132 | name = name.replace(/'/g, "\\'")
5133 | .replace(/\\"/g, '"')
5134 | .replace(/(^"|"$)/g, "'");
5135 | name = ctx.stylize(name, 'string');
5136 | }
5137 | }
5138 |
5139 | return name + ': ' + str;
5140 | }
5141 |
5142 |
5143 | function reduceToSingleString(output, base, braces) {
5144 | var numLinesEst = 0;
5145 | var length = output.reduce(function(prev, cur) {
5146 | numLinesEst++;
5147 | if (cur.indexOf('\n') >= 0) numLinesEst++;
5148 | return prev + cur.length + 1;
5149 | }, 0);
5150 |
5151 | if (length > 60) {
5152 | return braces[0] +
5153 | (base === '' ? '' : base + '\n ') +
5154 | ' ' +
5155 | output.join(',\n ') +
5156 | ' ' +
5157 | braces[1];
5158 | }
5159 |
5160 | return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1];
5161 | }
5162 |
5163 | function isArray(ar) {
5164 | return Array.isArray(ar) ||
5165 | (typeof ar === 'object' && objectToString(ar) === '[object Array]');
5166 | }
5167 |
5168 | function isRegExp(re) {
5169 | return typeof re === 'object' && objectToString(re) === '[object RegExp]';
5170 | }
5171 |
5172 | function isDate(d) {
5173 | return typeof d === 'object' && objectToString(d) === '[object Date]';
5174 | }
5175 |
5176 | function isError(e) {
5177 | return typeof e === 'object' && objectToString(e) === '[object Error]';
5178 | }
5179 |
5180 | function objectToString(o) {
5181 | return Object.prototype.toString.call(o);
5182 | }
5183 |
5184 | },{"./getEnumerableProperties":15,"./getName":17,"./getProperties":20}],24:[function(require,module,exports){
5185 | /*!
5186 | * Chai - flag utility
5187 | * Copyright(c) 2012-2014 Jake Luer
5188 | * MIT Licensed
5189 | */
5190 |
5191 | /*!
5192 | * Module dependancies
5193 | */
5194 |
5195 | var inspect = require('./inspect');
5196 | var config = require('../config');
5197 |
5198 | /**
5199 | * ### .objDisplay (object)
5200 | *
5201 | * Determines if an object or an array matches
5202 | * criteria to be inspected in-line for error
5203 | * messages or should be truncated.
5204 | *
5205 | * @param {Mixed} javascript object to inspect
5206 | * @name objDisplay
5207 | * @namespace Utils
5208 | * @api public
5209 | */
5210 |
5211 | module.exports = function (obj) {
5212 | var str = inspect(obj)
5213 | , type = Object.prototype.toString.call(obj);
5214 |
5215 | if (config.truncateThreshold && str.length >= config.truncateThreshold) {
5216 | if (type === '[object Function]') {
5217 | return !obj.name || obj.name === ''
5218 | ? '[Function]'
5219 | : '[Function: ' + obj.name + ']';
5220 | } else if (type === '[object Array]') {
5221 | return '[ Array(' + obj.length + ') ]';
5222 | } else if (type === '[object Object]') {
5223 | var keys = Object.keys(obj)
5224 | , kstr = keys.length > 2
5225 | ? keys.splice(0, 2).join(', ') + ', ...'
5226 | : keys.join(', ');
5227 | return '{ Object (' + kstr + ') }';
5228 | } else {
5229 | return str;
5230 | }
5231 | } else {
5232 | return str;
5233 | }
5234 | };
5235 |
5236 | },{"../config":4,"./inspect":23}],25:[function(require,module,exports){
5237 | /*!
5238 | * Chai - overwriteChainableMethod utility
5239 | * Copyright(c) 2012-2014 Jake Luer
5240 | * MIT Licensed
5241 | */
5242 |
5243 | /**
5244 | * ### overwriteChainableMethod (ctx, name, method, chainingBehavior)
5245 | *
5246 | * Overwites an already existing chainable method
5247 | * and provides access to the previous function or
5248 | * property. Must return functions to be used for
5249 | * name.
5250 | *
5251 | * utils.overwriteChainableMethod(chai.Assertion.prototype, 'length',
5252 | * function (_super) {
5253 | * }
5254 | * , function (_super) {
5255 | * }
5256 | * );
5257 | *
5258 | * Can also be accessed directly from `chai.Assertion`.
5259 | *
5260 | * chai.Assertion.overwriteChainableMethod('foo', fn, fn);
5261 | *
5262 | * Then can be used as any other assertion.
5263 | *
5264 | * expect(myFoo).to.have.length(3);
5265 | * expect(myFoo).to.have.length.above(3);
5266 | *
5267 | * @param {Object} ctx object whose method / property is to be overwritten
5268 | * @param {String} name of method / property to overwrite
5269 | * @param {Function} method function that returns a function to be used for name
5270 | * @param {Function} chainingBehavior function that returns a function to be used for property
5271 | * @namespace Utils
5272 | * @name overwriteChainableMethod
5273 | * @api public
5274 | */
5275 |
5276 | module.exports = function (ctx, name, method, chainingBehavior) {
5277 | var chainableBehavior = ctx.__methods[name];
5278 |
5279 | var _chainingBehavior = chainableBehavior.chainingBehavior;
5280 | chainableBehavior.chainingBehavior = function () {
5281 | var result = chainingBehavior(_chainingBehavior).call(this);
5282 | return result === undefined ? this : result;
5283 | };
5284 |
5285 | var _method = chainableBehavior.method;
5286 | chainableBehavior.method = function () {
5287 | var result = method(_method).apply(this, arguments);
5288 | return result === undefined ? this : result;
5289 | };
5290 | };
5291 |
5292 | },{}],26:[function(require,module,exports){
5293 | /*!
5294 | * Chai - overwriteMethod utility
5295 | * Copyright(c) 2012-2014 Jake Luer
5296 | * MIT Licensed
5297 | */
5298 |
5299 | /**
5300 | * ### overwriteMethod (ctx, name, fn)
5301 | *
5302 | * Overwites an already existing method and provides
5303 | * access to previous function. Must return function
5304 | * to be used for name.
5305 | *
5306 | * utils.overwriteMethod(chai.Assertion.prototype, 'equal', function (_super) {
5307 | * return function (str) {
5308 | * var obj = utils.flag(this, 'object');
5309 | * if (obj instanceof Foo) {
5310 | * new chai.Assertion(obj.value).to.equal(str);
5311 | * } else {
5312 | * _super.apply(this, arguments);
5313 | * }
5314 | * }
5315 | * });
5316 | *
5317 | * Can also be accessed directly from `chai.Assertion`.
5318 | *
5319 | * chai.Assertion.overwriteMethod('foo', fn);
5320 | *
5321 | * Then can be used as any other assertion.
5322 | *
5323 | * expect(myFoo).to.equal('bar');
5324 | *
5325 | * @param {Object} ctx object whose method is to be overwritten
5326 | * @param {String} name of method to overwrite
5327 | * @param {Function} method function that returns a function to be used for name
5328 | * @namespace Utils
5329 | * @name overwriteMethod
5330 | * @api public
5331 | */
5332 |
5333 | module.exports = function (ctx, name, method) {
5334 | var _method = ctx[name]
5335 | , _super = function () { return this; };
5336 |
5337 | if (_method && 'function' === typeof _method)
5338 | _super = _method;
5339 |
5340 | ctx[name] = function () {
5341 | var result = method(_super).apply(this, arguments);
5342 | return result === undefined ? this : result;
5343 | }
5344 | };
5345 |
5346 | },{}],27:[function(require,module,exports){
5347 | /*!
5348 | * Chai - overwriteProperty utility
5349 | * Copyright(c) 2012-2014 Jake Luer
5350 | * MIT Licensed
5351 | */
5352 |
5353 | /**
5354 | * ### overwriteProperty (ctx, name, fn)
5355 | *
5356 | * Overwites an already existing property getter and provides
5357 | * access to previous value. Must return function to use as getter.
5358 | *
5359 | * utils.overwriteProperty(chai.Assertion.prototype, 'ok', function (_super) {
5360 | * return function () {
5361 | * var obj = utils.flag(this, 'object');
5362 | * if (obj instanceof Foo) {
5363 | * new chai.Assertion(obj.name).to.equal('bar');
5364 | * } else {
5365 | * _super.call(this);
5366 | * }
5367 | * }
5368 | * });
5369 | *
5370 | *
5371 | * Can also be accessed directly from `chai.Assertion`.
5372 | *
5373 | * chai.Assertion.overwriteProperty('foo', fn);
5374 | *
5375 | * Then can be used as any other assertion.
5376 | *
5377 | * expect(myFoo).to.be.ok;
5378 | *
5379 | * @param {Object} ctx object whose property is to be overwritten
5380 | * @param {String} name of property to overwrite
5381 | * @param {Function} getter function that returns a getter function to be used for name
5382 | * @namespace Utils
5383 | * @name overwriteProperty
5384 | * @api public
5385 | */
5386 |
5387 | module.exports = function (ctx, name, getter) {
5388 | var _get = Object.getOwnPropertyDescriptor(ctx, name)
5389 | , _super = function () {};
5390 |
5391 | if (_get && 'function' === typeof _get.get)
5392 | _super = _get.get
5393 |
5394 | Object.defineProperty(ctx, name,
5395 | { get: function () {
5396 | var result = getter(_super).call(this);
5397 | return result === undefined ? this : result;
5398 | }
5399 | , configurable: true
5400 | });
5401 | };
5402 |
5403 | },{}],28:[function(require,module,exports){
5404 | /*!
5405 | * Chai - test utility
5406 | * Copyright(c) 2012-2014 Jake Luer
5407 | * MIT Licensed
5408 | */
5409 |
5410 | /*!
5411 | * Module dependancies
5412 | */
5413 |
5414 | var flag = require('./flag');
5415 |
5416 | /**
5417 | * # test(object, expression)
5418 | *
5419 | * Test and object for expression.
5420 | *
5421 | * @param {Object} object (constructed Assertion)
5422 | * @param {Arguments} chai.Assertion.prototype.assert arguments
5423 | * @namespace Utils
5424 | * @name test
5425 | */
5426 |
5427 | module.exports = function (obj, args) {
5428 | var negate = flag(obj, 'negate')
5429 | , expr = args[0];
5430 | return negate ? !expr : expr;
5431 | };
5432 |
5433 | },{"./flag":13}],29:[function(require,module,exports){
5434 | /*!
5435 | * Chai - transferFlags utility
5436 | * Copyright(c) 2012-2014 Jake Luer
5437 | * MIT Licensed
5438 | */
5439 |
5440 | /**
5441 | * ### transferFlags(assertion, object, includeAll = true)
5442 | *
5443 | * Transfer all the flags for `assertion` to `object`. If
5444 | * `includeAll` is set to `false`, then the base Chai
5445 | * assertion flags (namely `object`, `ssfi`, and `message`)
5446 | * will not be transferred.
5447 | *
5448 | *
5449 | * var newAssertion = new Assertion();
5450 | * utils.transferFlags(assertion, newAssertion);
5451 | *
5452 | * var anotherAsseriton = new Assertion(myObj);
5453 | * utils.transferFlags(assertion, anotherAssertion, false);
5454 | *
5455 | * @param {Assertion} assertion the assertion to transfer the flags from
5456 | * @param {Object} object the object to transfer the flags to; usually a new assertion
5457 | * @param {Boolean} includeAll
5458 | * @namespace Utils
5459 | * @name transferFlags
5460 | * @api private
5461 | */
5462 |
5463 | module.exports = function (assertion, object, includeAll) {
5464 | var flags = assertion.__flags || (assertion.__flags = Object.create(null));
5465 |
5466 | if (!object.__flags) {
5467 | object.__flags = Object.create(null);
5468 | }
5469 |
5470 | includeAll = arguments.length === 3 ? includeAll : true;
5471 |
5472 | for (var flag in flags) {
5473 | if (includeAll ||
5474 | (flag !== 'object' && flag !== 'ssfi' && flag != 'message')) {
5475 | object.__flags[flag] = flags[flag];
5476 | }
5477 | }
5478 | };
5479 |
5480 | },{}],30:[function(require,module,exports){
5481 | /*!
5482 | * assertion-error
5483 | * Copyright(c) 2013 Jake Luer
5484 | * MIT Licensed
5485 | */
5486 |
5487 | /*!
5488 | * Return a function that will copy properties from
5489 | * one object to another excluding any originally
5490 | * listed. Returned function will create a new `{}`.
5491 | *
5492 | * @param {String} excluded properties ...
5493 | * @return {Function}
5494 | */
5495 |
5496 | function exclude () {
5497 | var excludes = [].slice.call(arguments);
5498 |
5499 | function excludeProps (res, obj) {
5500 | Object.keys(obj).forEach(function (key) {
5501 | if (!~excludes.indexOf(key)) res[key] = obj[key];
5502 | });
5503 | }
5504 |
5505 | return function extendExclude () {
5506 | var args = [].slice.call(arguments)
5507 | , i = 0
5508 | , res = {};
5509 |
5510 | for (; i < args.length; i++) {
5511 | excludeProps(res, args[i]);
5512 | }
5513 |
5514 | return res;
5515 | };
5516 | };
5517 |
5518 | /*!
5519 | * Primary Exports
5520 | */
5521 |
5522 | module.exports = AssertionError;
5523 |
5524 | /**
5525 | * ### AssertionError
5526 | *
5527 | * An extension of the JavaScript `Error` constructor for
5528 | * assertion and validation scenarios.
5529 | *
5530 | * @param {String} message
5531 | * @param {Object} properties to include (optional)
5532 | * @param {callee} start stack function (optional)
5533 | */
5534 |
5535 | function AssertionError (message, _props, ssf) {
5536 | var extend = exclude('name', 'message', 'stack', 'constructor', 'toJSON')
5537 | , props = extend(_props || {});
5538 |
5539 | // default values
5540 | this.message = message || 'Unspecified AssertionError';
5541 | this.showDiff = false;
5542 |
5543 | // copy from properties
5544 | for (var key in props) {
5545 | this[key] = props[key];
5546 | }
5547 |
5548 | // capture stack trace
5549 | ssf = ssf || arguments.callee;
5550 | if (ssf && Error.captureStackTrace) {
5551 | Error.captureStackTrace(this, ssf);
5552 | } else {
5553 | this.stack = new Error().stack;
5554 | }
5555 | }
5556 |
5557 | /*!
5558 | * Inherit from Error.prototype
5559 | */
5560 |
5561 | AssertionError.prototype = Object.create(Error.prototype);
5562 |
5563 | /*!
5564 | * Statically set name
5565 | */
5566 |
5567 | AssertionError.prototype.name = 'AssertionError';
5568 |
5569 | /*!
5570 | * Ensure correct constructor
5571 | */
5572 |
5573 | AssertionError.prototype.constructor = AssertionError;
5574 |
5575 | /**
5576 | * Allow errors to be converted to JSON for static transfer.
5577 | *
5578 | * @param {Boolean} include stack (default: `true`)
5579 | * @return {Object} object that can be `JSON.stringify`
5580 | */
5581 |
5582 | AssertionError.prototype.toJSON = function (stack) {
5583 | var extend = exclude('constructor', 'toJSON', 'stack')
5584 | , props = extend({ name: this.name }, this);
5585 |
5586 | // include stack if exists and not turned off
5587 | if (false !== stack && this.stack) {
5588 | props.stack = this.stack;
5589 | }
5590 |
5591 | return props;
5592 | };
5593 |
5594 | },{}],31:[function(require,module,exports){
5595 | module.exports = require('./lib/eql');
5596 |
5597 | },{"./lib/eql":32}],32:[function(require,module,exports){
5598 | /*!
5599 | * deep-eql
5600 | * Copyright(c) 2013 Jake Luer
5601 | * MIT Licensed
5602 | */
5603 |
5604 | /*!
5605 | * Module dependencies
5606 | */
5607 |
5608 | var type = require('type-detect');
5609 |
5610 | /*!
5611 | * Buffer.isBuffer browser shim
5612 | */
5613 |
5614 | var Buffer;
5615 | try { Buffer = require('buffer').Buffer; }
5616 | catch(ex) {
5617 | Buffer = {};
5618 | Buffer.isBuffer = function() { return false; }
5619 | }
5620 |
5621 | /*!
5622 | * Primary Export
5623 | */
5624 |
5625 | module.exports = deepEqual;
5626 |
5627 | /**
5628 | * Assert super-strict (egal) equality between
5629 | * two objects of any type.
5630 | *
5631 | * @param {Mixed} a
5632 | * @param {Mixed} b
5633 | * @param {Array} memoised (optional)
5634 | * @return {Boolean} equal match
5635 | */
5636 |
5637 | function deepEqual(a, b, m) {
5638 | if (sameValue(a, b)) {
5639 | return true;
5640 | } else if ('date' === type(a)) {
5641 | return dateEqual(a, b);
5642 | } else if ('regexp' === type(a)) {
5643 | return regexpEqual(a, b);
5644 | } else if (Buffer.isBuffer(a)) {
5645 | return bufferEqual(a, b);
5646 | } else if ('arguments' === type(a)) {
5647 | return argumentsEqual(a, b, m);
5648 | } else if (!typeEqual(a, b)) {
5649 | return false;
5650 | } else if (('object' !== type(a) && 'object' !== type(b))
5651 | && ('array' !== type(a) && 'array' !== type(b))) {
5652 | return sameValue(a, b);
5653 | } else {
5654 | return objectEqual(a, b, m);
5655 | }
5656 | }
5657 |
5658 | /*!
5659 | * Strict (egal) equality test. Ensures that NaN always
5660 | * equals NaN and `-0` does not equal `+0`.
5661 | *
5662 | * @param {Mixed} a
5663 | * @param {Mixed} b
5664 | * @return {Boolean} equal match
5665 | */
5666 |
5667 | function sameValue(a, b) {
5668 | if (a === b) return a !== 0 || 1 / a === 1 / b;
5669 | return a !== a && b !== b;
5670 | }
5671 |
5672 | /*!
5673 | * Compare the types of two given objects and
5674 | * return if they are equal. Note that an Array
5675 | * has a type of `array` (not `object`) and arguments
5676 | * have a type of `arguments` (not `array`/`object`).
5677 | *
5678 | * @param {Mixed} a
5679 | * @param {Mixed} b
5680 | * @return {Boolean} result
5681 | */
5682 |
5683 | function typeEqual(a, b) {
5684 | return type(a) === type(b);
5685 | }
5686 |
5687 | /*!
5688 | * Compare two Date objects by asserting that
5689 | * the time values are equal using `saveValue`.
5690 | *
5691 | * @param {Date} a
5692 | * @param {Date} b
5693 | * @return {Boolean} result
5694 | */
5695 |
5696 | function dateEqual(a, b) {
5697 | if ('date' !== type(b)) return false;
5698 | return sameValue(a.getTime(), b.getTime());
5699 | }
5700 |
5701 | /*!
5702 | * Compare two regular expressions by converting them
5703 | * to string and checking for `sameValue`.
5704 | *
5705 | * @param {RegExp} a
5706 | * @param {RegExp} b
5707 | * @return {Boolean} result
5708 | */
5709 |
5710 | function regexpEqual(a, b) {
5711 | if ('regexp' !== type(b)) return false;
5712 | return sameValue(a.toString(), b.toString());
5713 | }
5714 |
5715 | /*!
5716 | * Assert deep equality of two `arguments` objects.
5717 | * Unfortunately, these must be sliced to arrays
5718 | * prior to test to ensure no bad behavior.
5719 | *
5720 | * @param {Arguments} a
5721 | * @param {Arguments} b
5722 | * @param {Array} memoize (optional)
5723 | * @return {Boolean} result
5724 | */
5725 |
5726 | function argumentsEqual(a, b, m) {
5727 | if ('arguments' !== type(b)) return false;
5728 | a = [].slice.call(a);
5729 | b = [].slice.call(b);
5730 | return deepEqual(a, b, m);
5731 | }
5732 |
5733 | /*!
5734 | * Get enumerable properties of a given object.
5735 | *
5736 | * @param {Object} a
5737 | * @return {Array} property names
5738 | */
5739 |
5740 | function enumerable(a) {
5741 | var res = [];
5742 | for (var key in a) res.push(key);
5743 | return res;
5744 | }
5745 |
5746 | /*!
5747 | * Simple equality for flat iterable objects
5748 | * such as Arrays or Node.js buffers.
5749 | *
5750 | * @param {Iterable} a
5751 | * @param {Iterable} b
5752 | * @return {Boolean} result
5753 | */
5754 |
5755 | function iterableEqual(a, b) {
5756 | if (a.length !== b.length) return false;
5757 |
5758 | var i = 0;
5759 | var match = true;
5760 |
5761 | for (; i < a.length; i++) {
5762 | if (a[i] !== b[i]) {
5763 | match = false;
5764 | break;
5765 | }
5766 | }
5767 |
5768 | return match;
5769 | }
5770 |
5771 | /*!
5772 | * Extension to `iterableEqual` specifically
5773 | * for Node.js Buffers.
5774 | *
5775 | * @param {Buffer} a
5776 | * @param {Mixed} b
5777 | * @return {Boolean} result
5778 | */
5779 |
5780 | function bufferEqual(a, b) {
5781 | if (!Buffer.isBuffer(b)) return false;
5782 | return iterableEqual(a, b);
5783 | }
5784 |
5785 | /*!
5786 | * Block for `objectEqual` ensuring non-existing
5787 | * values don't get in.
5788 | *
5789 | * @param {Mixed} object
5790 | * @return {Boolean} result
5791 | */
5792 |
5793 | function isValue(a) {
5794 | return a !== null && a !== undefined;
5795 | }
5796 |
5797 | /*!
5798 | * Recursively check the equality of two objects.
5799 | * Once basic sameness has been established it will
5800 | * defer to `deepEqual` for each enumerable key
5801 | * in the object.
5802 | *
5803 | * @param {Mixed} a
5804 | * @param {Mixed} b
5805 | * @return {Boolean} result
5806 | */
5807 |
5808 | function objectEqual(a, b, m) {
5809 | if (!isValue(a) || !isValue(b)) {
5810 | return false;
5811 | }
5812 |
5813 | if (a.prototype !== b.prototype) {
5814 | return false;
5815 | }
5816 |
5817 | var i;
5818 | if (m) {
5819 | for (i = 0; i < m.length; i++) {
5820 | if ((m[i][0] === a && m[i][1] === b)
5821 | || (m[i][0] === b && m[i][1] === a)) {
5822 | return true;
5823 | }
5824 | }
5825 | } else {
5826 | m = [];
5827 | }
5828 |
5829 | try {
5830 | var ka = enumerable(a);
5831 | var kb = enumerable(b);
5832 | } catch (ex) {
5833 | return false;
5834 | }
5835 |
5836 | ka.sort();
5837 | kb.sort();
5838 |
5839 | if (!iterableEqual(ka, kb)) {
5840 | return false;
5841 | }
5842 |
5843 | m.push([ a, b ]);
5844 |
5845 | var key;
5846 | for (i = ka.length - 1; i >= 0; i--) {
5847 | key = ka[i];
5848 | if (!deepEqual(a[key], b[key], m)) {
5849 | return false;
5850 | }
5851 | }
5852 |
5853 | return true;
5854 | }
5855 |
5856 | },{"buffer":undefined,"type-detect":33}],33:[function(require,module,exports){
5857 | module.exports = require('./lib/type');
5858 |
5859 | },{"./lib/type":34}],34:[function(require,module,exports){
5860 | /*!
5861 | * type-detect
5862 | * Copyright(c) 2013 jake luer
5863 | * MIT Licensed
5864 | */
5865 |
5866 | /*!
5867 | * Primary Exports
5868 | */
5869 |
5870 | var exports = module.exports = getType;
5871 |
5872 | /*!
5873 | * Detectable javascript natives
5874 | */
5875 |
5876 | var natives = {
5877 | '[object Array]': 'array'
5878 | , '[object RegExp]': 'regexp'
5879 | , '[object Function]': 'function'
5880 | , '[object Arguments]': 'arguments'
5881 | , '[object Date]': 'date'
5882 | };
5883 |
5884 | /**
5885 | * ### typeOf (obj)
5886 | *
5887 | * Use several different techniques to determine
5888 | * the type of object being tested.
5889 | *
5890 | *
5891 | * @param {Mixed} object
5892 | * @return {String} object type
5893 | * @api public
5894 | */
5895 |
5896 | function getType (obj) {
5897 | var str = Object.prototype.toString.call(obj);
5898 | if (natives[str]) return natives[str];
5899 | if (obj === null) return 'null';
5900 | if (obj === undefined) return 'undefined';
5901 | if (obj === Object(obj)) return 'object';
5902 | return typeof obj;
5903 | }
5904 |
5905 | exports.Library = Library;
5906 |
5907 | /**
5908 | * ### Library
5909 | *
5910 | * Create a repository for custom type detection.
5911 | *
5912 | * ```js
5913 | * var lib = new type.Library;
5914 | * ```
5915 | *
5916 | */
5917 |
5918 | function Library () {
5919 | this.tests = {};
5920 | }
5921 |
5922 | /**
5923 | * #### .of (obj)
5924 | *
5925 | * Expose replacement `typeof` detection to the library.
5926 | *
5927 | * ```js
5928 | * if ('string' === lib.of('hello world')) {
5929 | * // ...
5930 | * }
5931 | * ```
5932 | *
5933 | * @param {Mixed} object to test
5934 | * @return {String} type
5935 | */
5936 |
5937 | Library.prototype.of = getType;
5938 |
5939 | /**
5940 | * #### .define (type, test)
5941 | *
5942 | * Add a test to for the `.test()` assertion.
5943 | *
5944 | * Can be defined as a regular expression:
5945 | *
5946 | * ```js
5947 | * lib.define('int', /^[0-9]+$/);
5948 | * ```
5949 | *
5950 | * ... or as a function:
5951 | *
5952 | * ```js
5953 | * lib.define('bln', function (obj) {
5954 | * if ('boolean' === lib.of(obj)) return true;
5955 | * var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ];
5956 | * if ('string' === lib.of(obj)) obj = obj.toLowerCase();
5957 | * return !! ~blns.indexOf(obj);
5958 | * });
5959 | * ```
5960 | *
5961 | * @param {String} type
5962 | * @param {RegExp|Function} test
5963 | * @api public
5964 | */
5965 |
5966 | Library.prototype.define = function (type, test) {
5967 | if (arguments.length === 1) return this.tests[type];
5968 | this.tests[type] = test;
5969 | return this;
5970 | };
5971 |
5972 | /**
5973 | * #### .test (obj, test)
5974 | *
5975 | * Assert that an object is of type. Will first
5976 | * check natives, and if that does not pass it will
5977 | * use the user defined custom tests.
5978 | *
5979 | * ```js
5980 | * assert(lib.test('1', 'int'));
5981 | * assert(lib.test('yes', 'bln'));
5982 | * ```
5983 | *
5984 | * @param {Mixed} object
5985 | * @param {String} type
5986 | * @return {Boolean} result
5987 | * @api public
5988 | */
5989 |
5990 | Library.prototype.test = function (obj, type) {
5991 | if (type === getType(obj)) return true;
5992 | var test = this.tests[type];
5993 |
5994 | if (test && 'regexp' === getType(test)) {
5995 | return test.test(obj);
5996 | } else if (test && 'function' === getType(test)) {
5997 | return test(obj);
5998 | } else {
5999 | throw new ReferenceError('Type test "' + type + '" not defined or invalid.');
6000 | }
6001 | };
6002 |
6003 | },{}],35:[function(require,module,exports){
6004 | arguments[4][33][0].apply(exports,arguments)
6005 | },{"./lib/type":36,"dup":33}],36:[function(require,module,exports){
6006 | /*!
6007 | * type-detect
6008 | * Copyright(c) 2013 jake luer
6009 | * MIT Licensed
6010 | */
6011 |
6012 | /*!
6013 | * Primary Exports
6014 | */
6015 |
6016 | var exports = module.exports = getType;
6017 |
6018 | /**
6019 | * ### typeOf (obj)
6020 | *
6021 | * Use several different techniques to determine
6022 | * the type of object being tested.
6023 | *
6024 | *
6025 | * @param {Mixed} object
6026 | * @return {String} object type
6027 | * @api public
6028 | */
6029 | var objectTypeRegexp = /^\[object (.*)\]$/;
6030 |
6031 | function getType(obj) {
6032 | var type = Object.prototype.toString.call(obj).match(objectTypeRegexp)[1].toLowerCase();
6033 | // Let "new String('')" return 'object'
6034 | if (typeof Promise === 'function' && obj instanceof Promise) return 'promise';
6035 | // PhantomJS has type "DOMWindow" for null
6036 | if (obj === null) return 'null';
6037 | // PhantomJS has type "DOMWindow" for undefined
6038 | if (obj === undefined) return 'undefined';
6039 | return type;
6040 | }
6041 |
6042 | exports.Library = Library;
6043 |
6044 | /**
6045 | * ### Library
6046 | *
6047 | * Create a repository for custom type detection.
6048 | *
6049 | * ```js
6050 | * var lib = new type.Library;
6051 | * ```
6052 | *
6053 | */
6054 |
6055 | function Library() {
6056 | if (!(this instanceof Library)) return new Library();
6057 | this.tests = {};
6058 | }
6059 |
6060 | /**
6061 | * #### .of (obj)
6062 | *
6063 | * Expose replacement `typeof` detection to the library.
6064 | *
6065 | * ```js
6066 | * if ('string' === lib.of('hello world')) {
6067 | * // ...
6068 | * }
6069 | * ```
6070 | *
6071 | * @param {Mixed} object to test
6072 | * @return {String} type
6073 | */
6074 |
6075 | Library.prototype.of = getType;
6076 |
6077 | /**
6078 | * #### .define (type, test)
6079 | *
6080 | * Add a test to for the `.test()` assertion.
6081 | *
6082 | * Can be defined as a regular expression:
6083 | *
6084 | * ```js
6085 | * lib.define('int', /^[0-9]+$/);
6086 | * ```
6087 | *
6088 | * ... or as a function:
6089 | *
6090 | * ```js
6091 | * lib.define('bln', function (obj) {
6092 | * if ('boolean' === lib.of(obj)) return true;
6093 | * var blns = [ 'yes', 'no', 'true', 'false', 1, 0 ];
6094 | * if ('string' === lib.of(obj)) obj = obj.toLowerCase();
6095 | * return !! ~blns.indexOf(obj);
6096 | * });
6097 | * ```
6098 | *
6099 | * @param {String} type
6100 | * @param {RegExp|Function} test
6101 | * @api public
6102 | */
6103 |
6104 | Library.prototype.define = function(type, test) {
6105 | if (arguments.length === 1) return this.tests[type];
6106 | this.tests[type] = test;
6107 | return this;
6108 | };
6109 |
6110 | /**
6111 | * #### .test (obj, test)
6112 | *
6113 | * Assert that an object is of type. Will first
6114 | * check natives, and if that does not pass it will
6115 | * use the user defined custom tests.
6116 | *
6117 | * ```js
6118 | * assert(lib.test('1', 'int'));
6119 | * assert(lib.test('yes', 'bln'));
6120 | * ```
6121 | *
6122 | * @param {Mixed} object
6123 | * @param {String} type
6124 | * @return {Boolean} result
6125 | * @api public
6126 | */
6127 |
6128 | Library.prototype.test = function(obj, type) {
6129 | if (type === getType(obj)) return true;
6130 | var test = this.tests[type];
6131 |
6132 | if (test && 'regexp' === getType(test)) {
6133 | return test.test(obj);
6134 | } else if (test && 'function' === getType(test)) {
6135 | return test(obj);
6136 | } else {
6137 | throw new ReferenceError('Type test "' + type + '" not defined or invalid.');
6138 | }
6139 | };
6140 |
6141 | },{}]},{},[1])(1)
6142 | });
--------------------------------------------------------------------------------