<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

 <title>JanDudek.com</title>
 <link href="http://jandudek.com/atom.xml" rel="self"/>
 <link href="http://jandudek.com/"/>
 <updated>2015-09-04T19:36:25+02:00</updated>
 <id>http://jandudek.com/</id>
 <author>
   <name>Jan Dudek</name>
   <email>jd@jandudek.com</email>
 </author>

 
 <entry>
   <title>Let’s talk about front-end performance</title>
   <link href="http://jandudek.com/2014/12/11/lets-talk-about-front-end-performance.html"/>
   <updated>2014-12-11T00:00:00+01:00</updated>
   <id>http://jandudek.com/2014/12/11/lets-talk-about-front-end-performance</id>
   <content type="html">&lt;p&gt;This is a video recording of a talk I gave at &lt;a href=&quot;http://summit.meetjs.pl/2014/&quot;&gt;meet.js Summit&lt;/a&gt; in Poznań on September 27, 2014.&lt;/p&gt;

&lt;iframe src=&quot;https://player.vimeo.com/video/114222532&quot; width=&quot;698&quot; height=&quot;392&quot; frameborder=&quot;0&quot; webkitallowfullscreen mozallowfullscreen allowfullscreen&gt;&lt;/iframe&gt;
</content>
 </entry>
 
 <entry>
   <title>JavaScript object model basics</title>
   <link href="http://jandudek.com/2012/11/09/javascript-object-model-basics.html"/>
   <updated>2012-11-09T00:00:00+01:00</updated>
   <id>http://jandudek.com/2012/11/09/javascript-object-model-basics</id>
   <content type="html">&lt;p&gt;The JavaScript object model is very often misunderstood subject among programmers. I&#39;d like to give my own attempt at describing some important bits. You may also want to check the talk &lt;a href=&quot;https://docs.google.com/presentation/d/1KynKQX7Gf_iT-RwaB8cx2gOUXufhyzqsD0_0ZGSNQ3U/edit&quot;&gt;&lt;i&gt;JavaScript basics&lt;/i&gt;&lt;/a&gt; that &lt;a href=&quot;https://twitter.com/janfilipowski&quot;&gt;yashke&lt;/a&gt; gave at September &lt;a href=&quot;http://drug.org.pl/&quot;&gt;DRUG&lt;/a&gt; drink-up.&lt;/p&gt;

&lt;h3&gt;Objects and prototypes&lt;/h3&gt;

&lt;p&gt;The idea is really simple. Every object is a dictionary that maps from string keys to values. Values can be any JavaScript values, like numbers, objects and functions. Moreover, every object has a special pointer to another object – its prototype, available via &lt;tt&gt;__proto__&lt;/tt&gt; property. When you look up object&#39;s property and it does not exist, the lookup continues to the object&#39;s &lt;tt&gt;__proto__&lt;/tt&gt;, then to &lt;tt&gt;__proto__&lt;/tt&gt;&#39;s &lt;tt&gt;__proto__&lt;/tt&gt; and so on. At the end of this chain stays an object known as &lt;tt&gt;Object.prototype&lt;/tt&gt;. It&#39;s &lt;tt&gt;__proto__&lt;/tt&gt; is &lt;tt&gt;null&lt;/tt&gt; and the lookup terminates.&lt;/p&gt;

&lt;p&gt;Here&#39;s an example:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;__proto__&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;__proto__&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;===&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;Object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;prototype&lt;/span&gt;
&lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;__proto__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;__proto__&lt;/span&gt;
&lt;span class=&quot;kc&quot;&gt;null&lt;/span&gt;

&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;__proto__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lorem&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;ipsum&amp;quot;&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;lorem&lt;/span&gt;
&lt;span class=&quot;s1&quot;&gt;&amp;#39;ipsum&amp;#39;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;I bet no-one would complain about JavaScript complexity if things were just like above. Unfortunately, the language complicates and obfuscates this simple idea.&lt;/p&gt;

&lt;p&gt;First of all, &lt;tt&gt;__proto__&lt;/tt&gt; is non-standard property. Of course every JavaScript implementation has to store &lt;tt&gt;__proto__&lt;/tt&gt; somewhere, but only some of them expose &lt;tt&gt;__proto__&lt;/tt&gt; to the programmer. The standard ways to set prototypes are either constructor functions or &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create&quot;&gt;Object.create&lt;/a&gt;. Keep in my mind the latter is not available in older browsers. We will describe the first approach.&lt;/p&gt;

&lt;p&gt;Let&#39;s say we have a function &lt;tt&gt;Foo&lt;/tt&gt;. Every function in JavaScript is an object. Every function object has a property called &lt;tt&gt;prototype&lt;/tt&gt;. When you evaluate &lt;tt&gt;new Foo()&lt;/tt&gt;, JavaScript executes the following:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;create new, empty object: &lt;tt&gt;{}&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;set its &lt;tt&gt;__proto__&lt;/tt&gt; to &lt;tt&gt;Foo.prototype&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;execute &lt;tt&gt;Foo&lt;/tt&gt; function with the newly created object available as &lt;tt&gt;this&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;return the newly created object, unless &lt;tt&gt;Foo&lt;/tt&gt; returned another object (then return this another object)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Because &lt;tt&gt;Foo.prototype&lt;/tt&gt; is an object, it&#39;s &lt;tt&gt;__proto__&lt;/tt&gt; already points to another object (it might be &lt;tt&gt;Object.prototype&lt;/tt&gt; or something else) and this is how the &lt;tt&gt;__proto__&lt;/tt&gt; chain forms.&lt;/p&gt;

&lt;p&gt;There are some corner cases, like what happens if &lt;tt&gt;Foo.prototype&lt;/tt&gt; is not an object, but we won&#39;t dig into such details. Check the &lt;a href=&quot;http://ecma-international.org/ecma-262/5.1/#sec-13.2.2&quot;&gt;spec&#39;s section 13.2.2&lt;/a&gt;, if you&#39;re really interested.&lt;/p&gt;


&lt;h3&gt;What about &lt;tt&gt;this&lt;/tt&gt;?&lt;/h3&gt;

&lt;p&gt;&lt;tt&gt;this&lt;/tt&gt; is a special variable that holds a &quot;current&quot; object. It&#39;s most sane to think about it as another argument to every function, often passed implicitly by the language.&lt;/p&gt;

&lt;p&gt;There are 4 ways of calling a function in JavaScript:&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;&lt;tt&gt;foo()&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;obj.foo()&lt;/tt&gt; / &lt;tt&gt;obj[&quot;foo&quot;]()&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;foo.call()&lt;/tt&gt; / &lt;tt&gt;foo.apply()&lt;/tt&gt;&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;new foo()&lt;/tt&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The critical difference between them is what becomes &lt;tt&gt;this&lt;/tt&gt; during the function&#39;s execution.&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;In first case, the host object (&lt;tt&gt;window&lt;/tt&gt; in browsers) becomes &lt;tt&gt;this&lt;/tt&gt;. This is often confusing.&lt;/li&gt;
	&lt;li&gt;In second case, &lt;tt&gt;obj&lt;/tt&gt; becomes &lt;tt&gt;this&lt;/tt&gt;. This makes sense.&lt;/li&gt;
	&lt;li&gt;&lt;tt&gt;call()&lt;/tt&gt; and &lt;tt&gt;apply()&lt;/tt&gt; are ways to set &lt;tt&gt;this&lt;/tt&gt; explicitly to any object you want. The difference between &lt;tt&gt;call&lt;/tt&gt; and &lt;tt&gt;apply&lt;/tt&gt; is how you pass other arguments – either as an array or not. &lt;tt&gt;foo.call(obj, 1, 2)&lt;/tt&gt; is equivalent to &lt;tt&gt;foo.apply(obj, [1, 2])&lt;/tt&gt;.&lt;/li&gt;
	&lt;li&gt;The last case, using &lt;tt&gt;new&lt;/tt&gt;, works as described previously.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Keep &lt;tt&gt;this&lt;/tt&gt; under your control&lt;/h3&gt;

&lt;p&gt;It&#39;s very important to understand the difference between first and second form. In JavaScript, the invocation operator &lt;tt&gt;()&lt;/tt&gt; distinguishes whether it&#39;s applied to a refinement (an expression with dot or &lt;tt&gt;[]&lt;/tt&gt;). (&lt;a href=&quot;http://ecma-international.org/ecma-262/5.1/#sec-11.2.3&quot;&gt;11.2.3 in the spec&lt;/a&gt;).&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;obj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* our obj */&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* host object, i.e. window in browser */&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This distinction often leads to mistakes, especially when passing callback functions. Imagine the following code:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;kd&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;obj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;nx&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;document&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;results&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
	&lt;span class=&quot;nx&quot;&gt;loadData&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
	&lt;span class=&quot;nx&quot;&gt;showResults&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;innerHTML&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;results&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;loadData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;showResults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Can you see the mistake? Of course &lt;tt&gt;loadData&lt;/tt&gt; will execute callback, losing the &lt;tt&gt;this&lt;/tt&gt; value, and &lt;tt&gt;showResults&lt;/tt&gt; will refer to &lt;tt&gt;elem&lt;/tt&gt; property on host object, not &lt;tt&gt;obj&lt;/tt&gt;! Hunting bugs like this is not funny.&lt;/p&gt;

&lt;p&gt;There are a couple of techniques for dealing with this problem. One of them is using &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind&quot;&gt;&lt;tt&gt;Function.prototype.bind()&lt;/tt&gt;&lt;/a&gt;, which was introduced in ECMAScript 5 (again, not available in some older browsers). Hopefully by now it&#39;s clear that &lt;tt&gt;Function.prototype.bind&lt;/tt&gt; is a property &lt;tt&gt;bind&lt;/tt&gt; available on all function objects (because they have &lt;tt&gt;__proto__&lt;/tt&gt; set to &lt;tt&gt;Function.prototype&lt;/tt&gt;).&lt;/p&gt;

&lt;p&gt;Back to our example:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-javascript&quot; data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;showResults&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;showResults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bind&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;loadData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;showResults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;tt&gt;bind&lt;/tt&gt; returns new function, a wrapper that, once executed, will &lt;tt&gt;showResults.call(obj)&lt;/tt&gt;, thus making sure that &lt;tt&gt;this&lt;/tt&gt; is the object we wanted.&lt;/p&gt;

&lt;p&gt;If you&#39;re using CoffeeScript, it&#39;s a good idea to always define methods using fat arrow &lt;tt&gt;=&gt;&lt;/tt&gt;, which is compiled to &lt;tt&gt;bind&lt;/tt&gt;ing methods during object creation. (To be more specific, CoffeScript has more than one way to compile fat arrow).&lt;/p&gt;

&lt;h3&gt;Summary&lt;/h3&gt;

&lt;p&gt;There are some crazy quirks in JavaScript, but prototypes are not among them.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Testing deferreds</title>
   <link href="http://jandudek.com/2012/02/18/testing-deferreds.html"/>
   <updated>2012-02-18T00:00:00+01:00</updated>
   <id>http://jandudek.com/2012/02/18/testing-deferreds</id>
   <content type="html">&lt;p class=&quot;meta&quot;&gt;18 February 2012 - Wrocław&lt;/p&gt;

&lt;p&gt;If you&#39;ve carefully read &lt;a href=&quot;http://jandudek.com/2012/01/29/implementing-popups-in-diy-mvc.html&quot;&gt;my last post&lt;/a&gt; and &lt;a href=&quot;https://gist.github.com/a2144a9174db65049e1d/ddbffc9f863d9ccb1556c6d240302cc3bbd8d76d&quot;&gt;its sample code&lt;/a&gt;, you may have spotted how I&#39;m using deferreds for &lt;tt&gt;FacebookAdapter&lt;/tt&gt;. While writing tests for the example, I came up with an idea, how we could test methods that return deferreds.&lt;/p&gt;

&lt;h3&gt;What are deferreds?&lt;/h3&gt;

&lt;p&gt;Do you use deferreds in your projects? It&#39;s a very good pattern for dealing with asynchronous code. The idea is  that async function instead of accepting callbacks as arguments will return a &quot;promise&quot; object. You can bind you own callbacks to promise success/failure and they will run once promise is &quot;resolved&quot; or &quot;rejected&quot;.&lt;/p&gt;

&lt;p&gt;Here&#39;s an example:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;@facebook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;login&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;done&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;showLinksForLoggedIn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hideLogin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FacebookAdapter&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;login: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;Deferred&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;(dfr) =&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;# do some Facebook async stuff here, and call dfr.resolve() when ready&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;promise&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Once &lt;tt&gt;dfr.resolve()&lt;/tt&gt; is called, every function that you bound to the promise with &lt;tt&gt;done()&lt;/tt&gt; will be called. Conversely, calling &lt;tt&gt;dfr.reject()&lt;/tt&gt; will run callbacks bound with &lt;tt&gt;fail()&lt;/tt&gt; method.&lt;/p&gt;

&lt;p&gt;You&#39;ll find more detailed explanation in &lt;a href=&quot;http://jquery-deferred.heroku.com/&quot;&gt;slides from my talk&lt;/a&gt; presented at RailsCamp 2011 and of course &lt;a href=&quot;http://api.jquery.com/category/deferred-object/&quot;&gt;jQuery docs&lt;/a&gt;. There are many implementations of deferred pattern other than the jQuery one, like &lt;a href=&quot;https://github.com/medikoo/deferred&quot;&gt;this one by medikoo&lt;/a&gt; (but it&#39;s seems targeted at Node.js).&lt;/p&gt;

&lt;h3&gt;Deferreds vs events&lt;/h3&gt;

&lt;p&gt;The other common pattern to structure async code is using events. They are great in many cases, like responding to user actions. However, deferreds are better when dealing with async computations or communication:&lt;/p&gt;

&lt;ul&gt;
	&lt;li&gt;Deferred represents *one* instance of computation. You don&#39;t need to worry about your callback being run multiple times unexpectedly (like, for example, if someone called &lt;tt&gt;facebook.login()&lt;/tt&gt; again and you were bound to event like &lt;tt&gt;facebook:loggedIn&lt;/tt&gt;).&lt;/li&gt;
	&lt;li&gt;The callbacks will run even if you bind to already resolved promise - you don&#39;t have to care whether something is still going on or just finished.&lt;/li&gt;
	&lt;li&gt;It&#39;s very easy to run things in parallel and wait for all computations to finish - using &lt;tt&gt;$.when(oneDeferred, anotherOne, ...).done(doMyStuff)&lt;/tt&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Back to testing&lt;/h3&gt;

&lt;p&gt;When dealing with callback-based async code, Jasmine tests usually involve spying on the async method and running callback after the spy was called. There was even an example of this approach in samples for my previous post:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;spyOn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;facebook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;showWallPostDialog&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# later, when facebook.showWallPostDialog has been called&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;callback = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;facebook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;showWallPostDialog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mostRecentCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is hardly elegant or readable, so I thought we could do better with deferreds. What about this?&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;spyOn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;facebook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;showWallPostDialog&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;andReturnDeferred&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# later, when facebook.showWallPostDialog has been called&lt;/span&gt;
&lt;span class=&quot;nx&quot;&gt;facebook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;showWallPostDialog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;resolve&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It turns out to be quite easy to implement in Jasmine. When writing the last post, it was quick&#39;n&#39;dirty trick, but today I&#39;ve put together a &lt;a href=&quot;https://gist.github.com/1859787&quot;&gt;cleaner implementation&lt;/a&gt; (and I&#39;ve updated &lt;tt&gt;FacebookAdapter&lt;/tt&gt; mock in &lt;a href=&quot;https://gist.github.com/a2144a9174db65049e1d&quot;&gt;example for previous post&lt;/a&gt;). I really like Jasmine&#39;s simplicity and hackability. It&#39;s so easy to hook into the library and create all kinds of things you need.&lt;/p&gt;

&lt;p&gt;Please keep in mind we&#39;re extending a class we dont own (&lt;tt&gt;jasmine.Spy&lt;/tt&gt;), so I&#39;d advise to be careful, especially when upgrading Jasmine or using other 3rd party extensions.&lt;/p&gt;

&lt;p&gt;I hope you&#39;ve enjoyed reading this post as much as I&#39;ve enjoyed writing it! :-)&lt;/p&gt;

&lt;h3&gt;Post scriptum&lt;/h3&gt;
&lt;p&gt;Have you already bought your ticket for &lt;a href=&quot;http://wrocloverb.com/&quot;&gt;wroc_love.rb&lt;/a&gt;? It&#39;s going to be this year&#39;s best opportunity to drink beers and discuss with other hackers!&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Implementing popups in do-it-yourself MVC</title>
   <link href="http://jandudek.com/2012/01/29/implementing-popups-in-diy-mvc.html"/>
   <updated>2012-01-29T00:00:00+01:00</updated>
   <id>http://jandudek.com/2012/01/29/implementing-popups-in-diy-mvc</id>
   <content type="html">&lt;p class=&quot;meta&quot;&gt;29 January 2012 - Wrocław&lt;/p&gt;


&lt;p&gt;The goal of this post is to describe how I&#39;ve implemented a (not very complex) feature in one of my projects. I hope it will give you a peek into my architecture choices and show how to build a JavaScript MVC app without MVC framework.&lt;/p&gt;

&lt;p&gt;Some ideas presented here were developed in our team while working on &lt;a href=&quot;http://gameboxed.com/&quot;&gt;Gameboxed&lt;/a&gt;, but this post does not necessarily reflect opinions of my teammates :)&lt;/p&gt;

&lt;p&gt;We&#39;ll use &lt;a href=&quot;http://jquery.com/&quot;&gt;jQuery&lt;/a&gt; - but only in the view layer, except utilities like &lt;tt&gt;$.extend&lt;/tt&gt;. We also need implementation of observer pattern (sometimes called EventEmitter) - the examples use my own, tiny &lt;a href=&quot;./mvc-popups-example/lib/observable.js&quot;&gt;Observable&lt;/a&gt; library, but you could just as well borrow &lt;a href=&quot;https://github.com/documentcloud/backbone/blob/0.5.3/backbone.js#L55&quot;&gt;Backbone.Events&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;At the end of the post you&#39;ll find links to working example and source code.&lt;/p&gt;

&lt;p&gt;Ok, let&#39;s begin.&lt;/p&gt;

&lt;p&gt;What is a popup in terms of MVC? Popup is a kind of widget. Widget consists of a view and a controller. Each time we want to display a popup, we&#39;ll have a controller object of class with name ending &lt;tt&gt;*Popup&lt;/tt&gt; and another one - view - with name like &lt;tt&gt;*PopupView&lt;/tt&gt;. The controller can talk to the model and receive events from the view. The view should be dumb.&lt;/p&gt;

&lt;p&gt;Who will start displaying a popup? In my understanding of MVC, this is role of the controller, often in response to an event from the view.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MainController&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;constructor: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(@view) -&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bind&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;about:clicked&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;popup = &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AboutPopup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AboutPopupView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This example looks a bit too verbose and keeps a hardcoded dependency on &lt;tt&gt;AboutPopup&lt;/tt&gt; and &lt;tt&gt;AboutPopupView&lt;/tt&gt; classes. If you&#39;ve read my &lt;a href=&quot;http://jandudek.com/2012/01/03/factories-in-javascript.html&quot;&gt;last post about factories&lt;/a&gt;, you might already know how I&#39;d solve it:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MainController&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;constructor: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(@view, createAboutPopup) -&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bind&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;about:clicked&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;popup = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createAboutPopup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# in application bootstrap:&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;createAboutPopup = &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AboutPopup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AboutPopupView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;mainController = &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MainController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MainView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;createAboutPopup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We want to be able to display many popups, but not simultanously, rather one after the other. They cannot overlap, becuase this is ugly and confusing. That&#39;s why we&#39;ll have a queue object, responsible for showing next popup after one is closed (which they&#39;ll indicate by triggering &lt;tt&gt;closed&lt;/tt&gt; event).&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MainController&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;constructor: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(@view, @popupQueue, createAboutPopup, createAnotherPopup) -&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bind&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;about:clicked&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;@popupQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createAboutPopup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;@popupQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createAnotherPopup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Popups should be modal, which means other parts of interface have to be blocked while popup is visible. We&#39;ll achieve this using an &quot;overlay&quot; - semi-transparent div laid over page content. We want to have only one overlay, so its appearance will also be managed by queue. This leads us to the conclusion, that popup queue is also a kind of widget - it consists of a controller (&lt;tt&gt;PopupQueue&lt;/tt&gt;) and a view (&lt;tt&gt;PopupQueueView&lt;/tt&gt;).&lt;/p&gt;

&lt;p&gt;Ok, enough philosophy, back to reality. Here&#39;s Jasmine spec for our queue:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;nx&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;PopupQueue&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nx&quot;&gt;beforeEach&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@popupQueueView = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;jasmine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;createSpyObj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;popupQueueView&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;showOverlay&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;hideOverlay&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;append&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;remove&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@popupQueue = &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PopupQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popupQueueView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;nx&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;when registered two popups&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;beforeEach&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;mockPopupView = &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Observable&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;mockPopup = &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(view) -&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;({&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;view: &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Observable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;vi&quot;&gt;@popup1View = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mockPopupView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@popup1 = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mockPopup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popup1View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;vi&quot;&gt;@popup2View = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mockPopupView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;vi&quot;&gt;@popup2 = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mockPopup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popup2View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;nx&quot;&gt;@popupQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popup1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;@popupQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popup2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;should display overlay&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popupQueueView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;showOverlay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;should display only first popup view&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popupQueueView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;callCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popupQueueView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mostRecentCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popup1View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;nx&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;when first popup is closed&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;beforeEach&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;@popup1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;closed&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;should remove first popup view&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popupQueueView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;callCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popupQueueView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mostRecentCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popup1View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;should display second popup view&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popupQueueView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;callCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popupQueueView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mostRecentCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popup2View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

      &lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;should not hide overlay&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popupQueueView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hideOverlay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;not&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

      &lt;span class=&quot;nx&quot;&gt;describe&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;when second popup is closed&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;beforeEach&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt;
          &lt;span class=&quot;nx&quot;&gt;@popup2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;trigger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;closed&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

          &lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;should remove second popup view&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popupQueueView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;callCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toEqual&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popupQueueView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;mostRecentCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toBe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popup2View&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

          &lt;span class=&quot;nx&quot;&gt;it&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;should hide overlay&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nx&quot;&gt;expect&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@popupQueueView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hideOverlay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;toHaveBeenCalled&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The implementation should be left as an exercise for the reader, but I&#39;ll need it later in this post, so here&#39;s the code:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PopupQueue&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;constructor: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(@view) -&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@queue = &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;register: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(popup) =&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;@queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;@queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;showOverlay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;@processNext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;processNext: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;@queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;popup = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bind&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;closed&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;@hidePopup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;@queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;nx&quot;&gt;@processNext&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;@displayPopup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hideOverlay&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;displayPopup: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(popup) =&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;hidePopup: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(popup) =&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And here&#39;s PopupQueueView:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PopupQueueView&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;constructor: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@elem = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;lt;div class=&amp;quot;popups&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;showOverlay: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;&amp;lt;div class=&amp;quot;overlay&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;appendTo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fadeIn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;hideOverlay: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;@elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;.overlay&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;fadeOut&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;@elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;.overlay&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;append: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(subview) =&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;@elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;subview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;remove: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(subview) =&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;@elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;find&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;subview&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Is it dumb? I think it is. I don&#39;t feel the need to unit-test such views. I&#39;ll click through the application anyway to see if animation looks good and CSS is OK.&lt;/p&gt;

&lt;p&gt;Finally, we&#39;ll need the Popup and PopupView classes. They&#39;re fairly straithforward:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AboutPopup&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;constructor: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(@view) -&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Observable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bind&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;close:clicked&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;@trigger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;closed&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AboutPopupView&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;constructor: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Observable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;vi&quot;&gt;@elem = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;this&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;getHtml&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;@elem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;on&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;click&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;a.close&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;(e) =&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;preventDefault&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;@trigger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;close:clicked&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;getHtml: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;      &amp;lt;div class=&amp;quot;popup about&amp;quot;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;        &amp;lt;a href=&amp;quot;#&amp;quot; class=&amp;quot;close&amp;quot;&amp;gt;Close&amp;lt;/a&amp;gt;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;      &amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;    &amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The controller (&lt;tt&gt;AboutPopup&lt;/tt&gt;) forwards event triggered when user clicks &quot;Close&quot;, the queue will catch it and remove the view.&lt;/p&gt;

&lt;p&gt;So, to sum up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;we divide popups to controllers and views&lt;/li&gt;
&lt;li&gt;we use a queue that orchestrates their visibility&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;The benefits of this approach:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Popup as a controller may contain any complex logic, depend on many models etc. - anything you need. The caller doesn&#39;t know anything about it. The view may be just a message, may contain complex HTML, use localization, and so on.&lt;/li&gt;
&lt;li&gt;It&#39;s easy to reuse popup classes with different views, e.g. one controller for class with just &quot;close&quot; button, but different views for different content. Popups are objects, so we can use any OO techniques to make them DRY and still maintainable.&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Basically, every time we need some custom behaviour, we have a place to put it in. How often do we need it? In my last application, from which these examples come from, 7 of 10 popups were &quot;custom&quot; and needed specialized classes.&lt;/p&gt;

&lt;h3&gt;There&#39;s more...&lt;/h3&gt;


&lt;p&gt;We&#39;ll squeeze even more from this code. Suppose your app uses &lt;a href=&quot;https://github.com/facebook/facebook-js-sdk&quot;&gt;Facebook JavaScript SDK&lt;/a&gt; and you want to display wall post dialog - something like this:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;./wall-post.png&quot; alt=&quot;Screenshot of Facebook wall post popup&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Seems like another kind of popup, don&#39;t you think? It would be great to put them in our queue, so they&#39;re modal (just like any other popup, with overlay blocking rest of the interface) and so we can easily display them between other popups. In my opinion this results in much better user experience. We&#39;ll also have just one API to display popups, with no exception for those Facebook ones.&lt;/p&gt;

&lt;p&gt;The (small) problem is that Facebook SDK does not follow MVC pattern, and even if it did, it would not follow our conventions with appending subviews. So one of our popups won&#39;t be really MVC, but it doesn&#39;t bother us, because no-one will know (maybe except &lt;tt&gt;PopupQueue&lt;/tt&gt;). This is the kind of &quot;code smells&quot; that I don&#39;t care about - when our dirty implementation does not leak anywhere else, because the interface is clean.&lt;/p&gt;

&lt;p&gt;The only changes are that &lt;tt&gt;displayPopup&lt;/tt&gt;/&lt;tt&gt;hidePopup&lt;/tt&gt; in &lt;tt&gt;PopupQueue&lt;/tt&gt; have to be altered to support popups that will display/hide themselves, just like our Facebook ones. We discover whether a popup manages itself by looking if it supports &lt;tt&gt;display&lt;/tt&gt;/&lt;tt&gt;hide&lt;/tt&gt; methods.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;nv&quot;&gt;displayPopup: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(popup) =&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;hidePopup: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(popup) =&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hide&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;?&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;hide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;remove&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And here&#39;s our example wall-post-popup:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;WallPostPopup&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;constructor: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(@facebook) -&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Observable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;display: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;message = &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;I&amp;#39;m reading about JavaScript MVC on JanDudek.com&amp;quot;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;description = &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;Read more about JavaScript, Ruby and web development&amp;quot;&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;options =&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;link: &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;http://jandudek.com&amp;quot;&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;name: &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;message&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;description: &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;description&lt;/span&gt;

    &lt;span class=&quot;nv&quot;&gt;callback = &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;@trigger&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;closed&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;@facebook&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;showWallPostDialog&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;hide: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# hide method is just to indicate that this popup will manage hiding by itself&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Note that we don&#39;t call &lt;tt&gt;FB.ui&lt;/tt&gt; directly, but use an adapter object. This approach simplifies testing and makes much clearer what are dependencies of our class (everything listed in constructor arguments). Below is the relevant snippet of our adapter:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;FacebookAdapter&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;# ...&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;showWallPostDialog: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(options, callback) =&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;defaults =&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;method: &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;feed&amp;#39;&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;display: &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;#39;dialog&amp;#39;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;options = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;extend&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;defaults&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;FB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;ui&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;callback&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;




&lt;h3&gt;Still reading?&lt;/h3&gt;


&lt;p&gt;Ok, here&#39;s another issue. Some objects will need to show many popups, 3 or 4. So they&#39;ll receive 4 factories in constructor + &lt;tt&gt;popupQueue&lt;/tt&gt; object. Add a few other dependencies and suddenly arguments list of your class&#39; constructor spans three lines of code.&lt;/p&gt;

&lt;p&gt;Also, maybe knowing that there&#39;s a queue and popup objects is just too much knowledge for others? Basically you just want to fire a popup and don&#39;t care what will happen.&lt;/p&gt;

&lt;p&gt;That&#39;s why I decided to introduce another class: a &lt;tt&gt;PopupManager&lt;/tt&gt; (yeah, great name...). It knows about any kind of popup and you just call one method to display what you need.&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;nv&quot;&gt;popupQueue = &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PopupQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PopupQueueView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;popupManager = &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PopupManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;popupQueue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;about: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AboutPopup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AboutPopupView&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;wallPost: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;WallPostPopup&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;})&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;MainController&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;constructor: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(@view, @popupManager) -&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;@view&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;bind&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&amp;quot;about:clicked&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;@popupManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;about&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;nx&quot;&gt;@popupManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;display&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;quot;wallPost&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Here&#39;s the implementation:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;PopupManager&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;constructor: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(@queue, @factories) -&amp;gt;&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;display: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(args...) =&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;popup = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@create&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...)&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;@register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;register: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(popup) =&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;@queue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;register&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;popup&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;nv&quot;&gt;create: &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(args...) =&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;name = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;shift&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;factory = &lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;@factories&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;nx&quot;&gt;factory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;...)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If the list of factories passed to manager grows too large, or the manager exposes too many kinds of popups for other objects, you can split factories list and have many managers sharing one queue.&lt;/p&gt;

&lt;h3&gt;That&#39;s all, folks!&lt;/h3&gt;


&lt;p&gt;I hope that you&#39;ve found something useful in this long blog post, even if you&#39;re experienced JavaScript developer. Feel free to leave comments if you have any questions. Or if you think it was total bullshit :-)&lt;/p&gt;

&lt;p&gt;I&#39;ve also prepared a &lt;a href=&quot;./mvc-popups-example/&quot;&gt;a working example&lt;/a&gt; (&lt;a href=&quot;./mvc-popups-example/tests.html&quot;&gt;with tests&lt;/a&gt;). Here&#39;s its &lt;a href=&quot;https://gist.github.com/a2144a9174db65049e1d/ddbffc9f863d9ccb1556c6d240302cc3bbd8d76d&quot;&gt;source&lt;/a&gt;. In the example code there are many details and techniques that are beyond scope of this blog post. Again, feel free to ask in comments if you have any questions.&lt;/p&gt;
</content>
 </entry>
 
 <entry>
   <title>Factories in JavaScript</title>
   <link href="http://jandudek.com/2012/01/03/factories-in-javascript.html"/>
   <updated>2012-01-03T00:00:00+01:00</updated>
   <id>http://jandudek.com/2012/01/03/factories-in-javascript</id>
   <content type="html">&lt;p class=&quot;meta&quot;&gt;3 January 2012 - Wrocław&lt;/p&gt;


&lt;p&gt;In recent projects I&#39;ve been working on, I tried to use dependency injection in JavaScript as much as possible. The idea is to create instances of objects in one place, an &lt;tt&gt;Application&lt;/tt&gt; class or some other kind of initializer - instead of using &lt;tt&gt;new&lt;/tt&gt; all over the code. However, sometimes you need to defer object instantation for some reason, for example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the object&#39;s constructor needs parameters unknown during initalization&lt;/li&gt;
&lt;li&gt;there will be many instances of such object (possibly unknown number of them)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;This is easy to solve with factories: functions that create instances. I know it sounds a bit Java-like and enterprisy, but in JavaScript (and especially in CoffeeScript) it&#39;s really simple. Here are some examples:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;nv&quot;&gt;audioPlayer = &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AudioPlayersPool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;AudioPlayer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# the pool will create 10 instances of the player&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;clock = &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Clock&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;createCountdown = &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(seconds) -&amp;gt;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Countdown&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;clock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;seconds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# we don&amp;#39;t know how many countdowns we&amp;#39;ll need&lt;/span&gt;

&lt;span class=&quot;nv&quot;&gt;createTask = &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(attributes) -&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Task&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;serverSide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;gameWorld&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;clock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;earth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cannon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;createGameSession = &lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;(attributes) -&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;GameSession&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;serverSide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;createTask&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nv&quot;&gt;game = &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Game&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;serverSide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;createGameSession&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The last example shows another advantage. Before refactoring and moving &lt;tt&gt;GameSession&lt;/tt&gt; and &lt;tt&gt;Task&lt;/tt&gt; creation outside of &lt;tt&gt;Game&lt;/tt&gt; class, the initialization looked like this:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-coffeescript&quot; data-lang=&quot;coffeescript&quot;&gt;&lt;span class=&quot;nv&quot;&gt;game = &lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;Game&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nx&quot;&gt;serverSide&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;gameWorld&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;clock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;earth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nx&quot;&gt;cannon&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The first, refactored version is much better, because game only needs to create &lt;tt&gt;gameSessions&lt;/tt&gt;, not to deal with &lt;tt&gt;clock&lt;/tt&gt; or &lt;tt&gt;gameWorld&lt;/tt&gt; directly. Introducing factories leads to passing more specialized dependencies to other objects. Often it means less dependencies as well. As a result, objects have less knowledge about other parts of the application - which seems to be a good thing.&lt;/p&gt;

&lt;p&gt;I hope you&#39;ll find factories useful in your code too!&lt;/p&gt;

&lt;h3&gt;Further reading&lt;/h3&gt;


&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://misko.hevery.com/2010/05/29/dependency-injection-and-javascript-closures/&quot;&gt;http://misko.hevery.com/2010/05/29/dependency-injection-and-javascript-closures/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://misko.hevery.com/2008/07/18/breaking-the-law-of-demeter-is-like-looking-for-a-needle-in-the-haystack/&quot;&gt;http://misko.hevery.com/2008/07/18/breaking-the-law-of-demeter-is-like-looking-for-a-needle-in-the-haystack/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</content>
 </entry>
 
 <entry>
   <title>Bbq &amp; sessions pool</title>
   <link href="http://jandudek.com/2011/12/16/bbq-sessions-pool.html"/>
   <updated>2011-12-16T00:00:00+01:00</updated>
   <id>http://jandudek.com/2011/12/16/bbq-sessions-pool</id>
   <content type="html">&lt;p class=&quot;meta&quot;&gt;16 December 2011 - Wrocław&lt;/p&gt;


&lt;p&gt;Yesterday my friend &lt;a href=&quot;http://blog.robert.pankowecki.pl/&quot;&gt;paneq&lt;/a&gt; merged my patch that adds sessions pool to &lt;a href=&quot;https://github.com/drugpl/bbq&quot;&gt;Bbq&lt;/a&gt;. This is nice addition, especially because it&#39;s mine :) I will quickly describe the ideas behind bbq and my contribution.&lt;/p&gt;

&lt;p&gt;Bbq is a Ruby gem for acceptance testing of Web apps. The idea is to use objects - so called test actors - that have meaningful methods describing their actions and/or expectations. Similar to Cucumber, but without the natural language part (but still pretty much readable). Here&#39;s an example:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;vi&quot;&gt;@alice&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;TestUser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:driver&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:selenium&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@alice&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;visit_homepage&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@alice&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;click_link&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Posts&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@alice&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;see?&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;My post&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Bbq is rather thin wrapper around Capybara - an excellent gem that gives consistent API for different testing tools, like Selenium or rack-test.&lt;/p&gt;

&lt;p&gt;One of use cases where Bbq really shines is testing interaction between many users. Each TestUser instance has it&#39;s own Capybara session and you can mix actions of different users:&lt;/p&gt;

&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-ruby&quot; data-lang=&quot;ruby&quot;&gt;&lt;span class=&quot;vi&quot;&gt;@bob&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;TestUser&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@bob&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;visit_homepage&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@bob&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;click_link&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Posts&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@bob&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;see?&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;0 comments&amp;quot;&lt;/span&gt;

&lt;span class=&quot;vi&quot;&gt;@alice&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fill_in&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Comment&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:with&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Lorem ipsum&amp;quot;&lt;/span&gt;
&lt;span class=&quot;vi&quot;&gt;@alice&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;click_button&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Add comment&amp;quot;&lt;/span&gt;

&lt;span class=&quot;vi&quot;&gt;@bob&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;click_link&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;My post&amp;quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;vi&quot;&gt;@bob&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;see?&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;Lorem ipsum&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:within&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;#comments&amp;quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Please note that @alice and @bob can use different drivers, for example one of them might be using Selenium to execute JavaScripts and the other could use rack-test (and run much faster). You can even replace TestUser with &lt;a href=&quot;https://github.com/drugpl/bbq/issues/16&quot;&gt;TestClient&lt;/a&gt; - an API client - that issues HTTP requests without a browser. This is a great approach used in some of our Facebook games that expose REST API and also a &quot;traditional&quot; admin panel with regular views etc. Successful testing of such app often involves combination of rack_test, Selenium and API clients (and some client-side acceptance tests, but that&#39;s a different story).&lt;/p&gt;

&lt;p&gt;So what does my addition do? Before yesterday, each time you created a TestUser, a new Capybara session was created. This can be quite expensive, especially when using Selenium, as it means running a new browser instance. That&#39;s why we added a sessions pool, that reuses sessions between test cases. Each time you create a TestUser, it calls &lt;tt&gt;Bbq::Session.next&lt;/tt&gt;. If there are &quot;idle&quot; sessions, one of them is returned. Otherwise it creates a new one. All existing sessions are kept in &lt;tt&gt;Bbq::Session.pool&lt;/tt&gt; (i know, ugly global object) and released during test&#39;s teardown.&lt;/p&gt;

&lt;p&gt;You can skip using session pools by providing &lt;tt&gt;:pool =&gt; false&lt;/tt&gt; as TestUser option or by providing already created Capybara session with &lt;tt&gt;:session&lt;/tt&gt; option.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this post! If you&#39;re interested, try bbq today! It&#39;s really easy to get started. Bbq supports Test::Unit as well as RSpec out of the box, but you should be able to easily use it within any other test framework.&lt;/p&gt;

&lt;p&gt;PS. Bbq was developed by folks from &lt;a href=&quot;http://drug.org.pl/&quot;&gt;DRUG&lt;/a&gt;, a Ruby users group from Wroclaw area. If you live anywhere near, or if you want to visit Wroclaw, feel invited to one of our meetings! There&#39;s always a good amount of tech talks, flame wars and lots of beers. We&#39;re also organizing &lt;a href=&quot;http://wrocloverb.com/&quot;&gt;wroc_love.rb&lt;/a&gt;, great conference about Ruby &amp;amp; related topics.&lt;/p&gt;
</content>
 </entry>
 
</feed>
