-
Notifications
You must be signed in to change notification settings - Fork 70
/
index.html
236 lines (233 loc) · 16 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
<!DOCTYPE html>
<html lang="en">
<head>
<title>Core Plugin Concepts - Chai</title>
<link rel="icon" type="image/x-icon" href="/public/img/favicon.ico">
<script type="text/javascript">
var ghuser = 'logicalparadox'
, ghproject = 'chai';
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script src="/public/js/jquery-mousewheel.js"></script>
<script src="/public/js/antiscroll.js"></script>
<script src="/public/js/main.js?2.1.0"></script>
<script src="/public/js/guide.js"></script>
<link rel="stylesheet" href="/public/css/antiscroll.css?2.1.0" type="text/css" media="all">
<link rel="stylesheet" href="/public/css/main.css?2.1.0" type="text/css" media="all">
<script type="text/javascript">
var mpq = [];
mpq.push(["init", "d5e84615dbd02dbc359b0f76d0ed7cf5"]);
(function(){var b,a,e,d,c;b=document.createElement("script");b.type="text/javascript";
b.async=true;b.src=(document.location.protocol==="https:"?"https:":"http:")+
"//api.mixpanel.com/site_media/js/api/mixpanel.js";a=document.getElementsByTagName("script")[0];
a.parentNode.insertBefore(b,a);e=function(f){return function(){mpq.push(
[f].concat(Array.prototype.slice.call(arguments,0)))}};d=["init","track","track_links",
"track_forms","register","register_once","identify","name_tag","set_config"];for(c=0;c<
d.length;c++){mpq[d[c]]=e(d[c])}})();
</script>
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-26183904-6']);
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body class="guide">
<nav id="primary">
<div class="nav-wrap">
<div class="logo">
<h1><a href="/">Chai Assertion Library</a></h1>
</div>
<div class="navlist">
<ul>
<li><a href="/guide">Guide</a></li>
<li><a href="/api" class="">API</a></li>
<li><a href="/plugins">Plugins</a></li>
</ul>
</div>
</div>
</nav>
<div class="content">
<section id="content">
<nav id="guide" class="sidebar sticky">
<div id="guide-index" class="item primary "><span class="star"></span><a href="/guide/" class="title">Getting Started Guide</a></div>
<div class="line"></div>
<div id="installation" class="item primary "><span class="expand">+</span><span class="collapse">-</span><a href="/guide/installation/" class="title">Installation</a></div>
<div id="installation" class="subitems"><a href="/guide/installation/#node" id="node" class="item secondary group-installation">Node</a><a href="/guide/installation/#browser" id="browser" class="item secondary group-installation">Browser</a><a href="/guide/installation/#other" id="other" class="item secondary group-installation">Other Platforms</a>
</div>
<div id="styles" class="item primary "><span class="expand">+</span><span class="collapse">-</span><a href="/guide/styles/" class="title">Assertion Styles</a></div>
<div id="styles" class="subitems"><a href="/guide/styles/#assert" id="assert" class="item secondary group-styles">Assert</a><a href="/guide/styles/#expect" id="expect" class="item secondary group-styles">Expect</a><a href="/guide/styles/#should" id="should" class="item secondary group-styles">Should</a><a href="/guide/styles/#differences" id="differences" class="item secondary group-styles">Differences</a><a href="/guide/styles/#should-extras" id="should-extras" class="item secondary group-styles">Should Extras</a><a href="/guide/styles/#configure" id="configure" class="item secondary group-styles">Configuration</a>
</div>
<div id="plugins" class="item primary active expanded"><span class="expand">+</span><span class="collapse">-</span><a href="/guide/plugins/" class="title">Core Plugin Concepts</a></div>
<div id="plugins" class="subitems"><a href="#use" id="use" class="item secondary expanded scroll group-plugins">Accessing Utilities</a><a href="#flags" id="flags" class="item secondary expanded scroll group-plugins">Using Flags</a><a href="#assert" id="assert" class="item secondary expanded scroll group-plugins">Composing an Assertion</a>
</div>
<div id="helpers" class="item primary "><span class="expand">+</span><span class="collapse">-</span><a href="/guide/helpers/" class="title">Building a Helper</a></div>
<div id="helpers" class="subitems"><a href="/guide/helpers/#add_language_chain" id="add_language_chain" class="item secondary group-helpers">Adding Language Chains</a><a href="/guide/helpers/#add_property" id="add_property" class="item secondary group-helpers">Adding Properties</a><a href="/guide/helpers/#add_method" id="add_method" class="item secondary group-helpers">Adding Methods</a><a href="/guide/helpers/#add_method_as_property" id="add_method_as_property" class="item secondary group-helpers">Methods as Properties</a><a href="/guide/helpers/#overwrite_language_chain" id="overwrite_language_chain" class="item secondary group-helpers">Overwriting Language Chains</a><a href="/guide/helpers/#overwrite_property" id="overwrite_property" class="item secondary group-helpers">Overwriting Properties</a><a href="/guide/helpers/#overwrite_method" id="overwrite_method" class="item secondary group-helpers">Overwriting Methods</a>
</div>
<div id="resources" class="item primary "><span class="expand">+</span><span class="collapse">-</span><a href="/guide/resources/" class="title">Resources</a></div>
<div id="resources" class="subitems"><a href="/guide/resources/#help" id="help" class="item secondary group-resources">Getting Help</a><a href="/guide/resources/#contributor" id="contributor" class="item secondary group-resources">Contributing</a>
</div>
</nav>
<div class="documentation">
<div class="wrap">
<div class="rendered">
<div class="header"><h1 id="core-plugin-concepts">Core Plugin Concepts</h1>
<p>Plugins are for more than just writing vendor integrations. As a tester, one can write
a plugin to validate input data, assert schema validation on an object, or ensure proper behavior
on a dom element. The API is flexible enough that any synchronous tasks can easily be encapsulated
within a single assertion and reused throughout your tests.</p>
<p>This tutorial will show you how to access Chai's plugin API, use flags to transfer data through
the language chain, and write your first assertion (and thorough error messages). Once you have
finished here, <a href="/guide/helpers">Building a Helper</a> will show you how to compose properties and
methods for use on the Chai language chain.</p>
</div>
<article id="use-section"><h2 id="accessing-utilties">Accessing Utilties</h2>
<p>Chai comes with a number of utilities to assist in the construction of assertions,
but it does not provide these directly on the <code>chai</code> export. These can be accessed
by using the <code>use</code> method of the chai export, which accepts a single function as
an argument.</p>
<pre><code class="lang-javascript">chai.use(<span class="function"><span class="keyword">function</span> <span class="params">(_chai, utils)</span> {</span>
<span class="comment">// ...</span>
});</code></pre>
<p>The function which will be used gets passed two parameters to its scope. The first
is the <code>chai</code> export, the second is an object containing a number of utility
methods (we'll get to those in a minute).</p>
<p>The <code>chai</code> export is included so that you can build helpers that can be used
in multiple test files, or package your helpers as a plugin to share with the
community. A more appropriate pattern for creating helpers is as follows...</p>
<p>For our helper file: <code>test/helpers/model.js</code></p>
<pre><code class="lang-javascript">module.exports = <span class="function"><span class="keyword">function</span> <span class="params">(chai, utils)</span> {</span>
<span class="keyword">var</span> Assertion = chai.Assertion;
<span class="comment">// your helpers here</span>
};</code></pre>
<p>And, for our actual test: <code>test/person.js</code></p>
<pre><code class="lang-javascript"><span class="keyword">var</span> chai = require(<span class="string">'chai'</span>)
, chaiModel = require(<span class="string">'./helpers/model'</span>)
, expect = chai.expect;
chai.use(chaiModel);</code></pre>
<p>For the rest of this document, we will assume this structure...</p>
<ul>
<li>helper in external file</li>
<li><code>chai.Assertion</code> assigned to the <code>Assertion</code> variable</li>
<li>all of our helpers will be inside exported function, located where indicated</li>
</ul>
<p>The <code>Assertion</code> variable is now a constructor for an assertion chain;
<code>new Assertion(obj)</code> is now equivalent to <code>expect(obj)</code>.</p>
</article>
<article id="flags-section"><h2 id="using-flags">Using Flags</h2>
<p>The upper-most core concept of how assertions work internally is the concept of flags.
Each assertion has a set of mostly arbitrary flags - key:value pairs - associated with it.
Chai uses a small number of these internally, but the store is also available for developers
to expand on. </p>
<h3 id="flag-usage">flag usage</h3>
<p>The flag utility is exposed as <code>utils.flag</code> from within our <code>use</code> function. It can function
as either a getter or a setter, depending on the number of arguments passed to it.</p>
<pre><code class="lang-javascript"><span class="keyword">var</span> myAssert = <span class="keyword">new</span> Assertion(obj);
utils.flag(myAssert, <span class="string">'owner'</span>, <span class="string">'me'</span>); <span class="comment">// sets key `owner` to `me`</span>
<span class="keyword">var</span> owner = utils.flag(myAssert, <span class="string">'owner'</span>); <span class="comment">// get key `owner', returns value</span></code></pre>
<h3 id="object-flag">object flag</h3>
<p>The most important of Chai's reserved flags is the <code>object</code> flag. This is the subject
of an assertion.</p>
<pre><code class="lang-javascript"><span class="keyword">var</span> myAssert = <span class="keyword">new</span> Assertion(<span class="string">'Arthur Dent'</span>);
<span class="keyword">var</span> obj = flag(myAssert, <span class="string">'object'</span>); <span class="comment">// obj === 'Arthur Dent';</span></code></pre>
<p>This flag is so often used that a shortcut was provided as the <code>_obj</code> property of a
constructed assertion.</p>
<pre><code class="lang-javascript"><span class="keyword">var</span> obj = myAssert._obj; <span class="comment">// obj === `Arthur Dent`</span></code></pre>
<p>The following flags are used by Chai's core assertions. Side effects may occur should you
interfere with these.</p>
<ul>
<li><code>object</code>: (see above)</li>
<li><code>ssfi</code>: start stack function - used to prevent callback stacks from being shown in
errors.</li>
<li><code>message</code>: additional information to include with an error when using <code>assert</code> interface.</li>
<li><code>negate</code>: set when <code>.not</code> is included in the chain.</li>
<li><code>deep</code>: set when <code>.deep</code> is included in the chain. used by <code>equal</code> and <code>property</code></li>
<li><code>contains</code>: set when <code>include</code> or <code>contain</code> is used as a property.
changes the behavior of <code>keys</code>.</li>
<li><code>lengthOf</code>: set when <code>length</code> is used as a property. changes the behavior of
<code>above</code>, <code>below</code>, and <code>within</code>.</li>
</ul>
</article>
<article id="assert-section"><h2 id="composing-an-assertion">Composing an Assertion</h2>
<p>Before we begin adding methods and properties to the language chain, we should
first examine how to invoke an assertion, and the expected behavior should it fail.</p>
<p>For this, each constructed <code>Assertion</code> has a method called simply <code>assert</code>. It accepts
many parameters and its behavior can change depending on whether an assertion was
negated or not.</p>
<h3 id="basic-assertion">Basic Assertion</h3>
<p>To begin, we will construct Arthur again, then we can assert that he is who he says he is.</p>
<pre><code class="lang-javascript"><span class="keyword">var</span> arthur = <span class="keyword">new</span> Assertion(<span class="string">'Arthur Dent'</span>);
arthur.assert(
arthur._obj === <span class="string">'Arthur Dent'</span>
, <span class="string">"expected #{this} to be 'Arthur Dent'"</span>
, <span class="string">"expected #{this} to not be 'Arthur Dent'"</span>
);</code></pre>
<p>Chai will check the first argument; if it is <code>true</code> then the assertion passed, but if it is <code>false</code>
the assertion failed and the first error message will be thrown as part of a <code>chai.AssertionError</code>.
Conversely, if the language chain was negated, it will consider <code>false</code> a pass and <code>true</code> a failure.
The second error message will be included in the thrown error instead.</p>
<p>In all, the <code>assert</code> method accepts six arguments:</p>
<ol>
<li>a boolean (result of a truth test)</li>
<li>a string error message to be used if the first argument is <code>false</code></li>
<li>a string error message to be used if the assertion is negated and the first argument is <code>true</code></li>
<li>(optional) the expected value</li>
<li>(optional) the actual value, which will default to <code>_obj</code></li>
<li>(optional) a boolean which indicates whether to display a diff in addition to the message if the first argument is <code>false</code></li>
</ol>
<h3 id="composing-error-messages">Composing Error Messages</h3>
<p>As you can see from the above example, Chai can accept template tags to dynamically compose
the error message. When used, these template tags will be replaced with a stringified replacement
of the object in question. There are three template tags available.</p>
<ul>
<li><code>#{this}</code>: the <code>_obj</code> of the assertion</li>
<li><code>#{exp}</code>: the expected value, if it was provided in <code>assert</code></li>
<li><code>#{act}</code>: the actual value, defaults to <code>_obj</code> but can be overwritten by value provided in <code>assert</code></li>
</ul>
</article>
</div>
</div>
</div>
</section>
</div>
<footer>
<section id="footer">
<div class="branding">
<h3 class="fancy"><a href="#">Chai Assertion Library</a></h3>
</div>
<div class="list">
<ul>
<li><a href="/guide/installation/">Installation</a></li>
<li><a href="/guide/styles/">Interface Styles</a></li>
<li><a href="/guide/plugins/">Developing Plugins</a></li>
</ul>
</div>
<div class="list">
<ul>
<li><a href="/api/bdd/">Expect / Should API</a></li>
<li><a href="/api/assert/">Assert API</a></li>
<li><a href="/api/plugins/">Plugin Utility API</a></li>
</ul>
</div>
<div class="list">
<ul>
<li><a href="/guide/resources/">Getting Help</a></li>
<li><a href="/api/test/">Test Suite</a></li>
<li><a href="https://github.com/chaijs/chai/blob/master/History.md" target="_blank">Changelog</a></li>
</ul>
</div>
<div class="list">
<ul>
<li><a href="https://github.com/chaijs/chai/issues" target="_blank">Issues</a></li>
<li><a href="http://groups.google.com/group/chaijs" target="_blank">Google Group</a></li>
<li><a href="http://travis-ci.org/#!/chaijs/chai" target="_blank">Build Status</a></li>
</ul>
</div>
</section>
</footer>
</body>
</html>