@@ -273,119 +273,6 @@ Assertion.addChainableMethod('age', assertModelAge, chainModelAge);
273
273
274
274
Done. Now we can assert Arthur's exact age. We will pick up again with this example when learning how to overwrite methods.
275
275
276
- ### Methods as Properties
277
-
278
- Chai includes a unique utility that allows you to construct a language chain that can function
279
- as either a property or a method. We call these "chainable methods". Despite the fact that we
280
- demonstrated the "is model of model" as both a property and a method, these assertions are NOT
281
- a good use case for chainable methods.
282
-
283
- ##### When to Use
284
-
285
- To understand when to best use chainable methods we will examine a chainable method from Chai's
286
- core.
287
-
288
- ` ` ` javascript
289
- var arr = [ 1 , 2 , 3 ]
290
- , obj = { a: 1 , b: 2 };
291
-
292
- expect (arr).to .contain (2 );
293
- expect (obj).to .contain .key (' a' );
294
- ` ` `
295
-
296
- For this to work, two seperate functions are needed. One that will be invoked when the
297
- chain is used as either a property or a method, and one that will be invoked when only used
298
- as a method.
299
-
300
- In these examples, and with all of the other chainable methods in core, the only function
301
- of ` contain` as a property is to set a ` contains` flag to true. This indicates to ` keys` to
302
- behave differently. In this case, when ` key` is used in conjunction with ` contain` , it will check
303
- for the inclusion of a key, instead of checking the exact match to all keys.
304
-
305
- ##### When NOT to Use
306
-
307
- Let's say we set up a chainable method for ` model` to behave as we indicated above: do an ` instanceof `
308
- check if used as a property, and a ` _type` check if used as a method. The following conflict would occur...
309
-
310
- The following would work...
311
-
312
- ` ` ` javascript
313
- expect (arthur).to .be .a .model ;
314
- expect (arthur).to .be .a .model (' person' );
315
- expect (arr).to .not .be .a .model ;
316
- ` ` `
317
-
318
- But the following would not...
319
-
320
- ` ` ` javascript
321
- expect (arthur).to .not .be .a .model (' person' );
322
- ` ` `
323
-
324
- Remember, since the function used as the property assertion is invoked when also used as a method,
325
- and negation impacts ALL assertions after it is set, we would receive an error message resembling
326
- ` expected [object Model] not to be instance of [object Model]` . As such, please obey this general
327
- guideline when constructing chainable methods.
328
-
329
- > When constructing chainable methods, the property function should only serve to set a flag
330
- > for later modifying the behavior of an existing assertion.
331
-
332
- ##### An Appropriate Example
333
-
334
- For use with our model example, we are going to construct an example that allows us to test Arthur's
335
- age exactly, or chain into Chai's numerical comparators, such as ` above` , ` below` , and ` within` . You will
336
- need to learn how to overwrite methods without destroying core functionality, but we get to that a bit later.
337
-
338
- Our goal will allow for all of the following to pass.
339
-
340
- ` ` ` javascript
341
- expect (arthur).to .have .age (27 );
342
- expect (arthur).to .have .age .above (17 );
343
- expect (arthur).to .not .have .age .below (18 );
344
- ` ` `
345
-
346
- Let's start first by composing the two functions needed for a chainable method. First up is the function
347
- to use when invoking the ` age` method.
348
-
349
- ` ` ` javascript
350
- function assertModelAge (n ) {
351
- // make sure we are working with a model
352
- new Assertion (this ._obj ).to .be .instanceof (Model);
353
-
354
- // make sure we have an age and its a number
355
- var age = this ._obj .get (' age' );
356
- new Assertion (age).to .be .a (' number' );
357
-
358
- // do our comparison
359
- this .assert (
360
- age === n
361
- , " expected #{this} to have have #{exp} but got #{act}"
362
- , " expected #{this} to not have age #{act}"
363
- , n
364
- , age
365
- );
366
- }
367
- ` ` `
368
-
369
- By now, that should be self-explanitory. Now for our property function.
370
-
371
- ` ` ` javascript
372
- function chainModelAge () {
373
- utils .flag (this , ' model.age' , true );
374
- }
375
- ` ` `
376
-
377
- We will later teach our numerical comparators to look for that flag and change its behavior. Since we don't want to
378
- break the core methods, we will need to safely override that method, but we'll get to that in a minute. Let's
379
- finish up here first...
380
-
381
- ` ` ` javascript
382
- Assertion .addChainableMethod (' age' , assertModelAge, chainModelAge);
383
- ` ` `
384
-
385
- <a href="/api/plugins/#addChainableMethod-section" class="clean-button">View addChainableMethod API</a>
386
-
387
- Done. Now we can assert Arthur's exact age. We will pick up again with this example when learning how to overwrite methods.
388
-
389
276
## Overwriting Language Chains
390
277
391
278
Now that we can successfully add assertions to the language chain,
0 commit comments