public function chain($item = null)
 {
     list($item) = self::_wrapArgs(func_get_args(), 1);
     $__ = isset($this) && isset($this->_chained) && $this->_chained ? $this : __u($item);
     $__->_chained = true;
     return $__;
 }
 public function testValue()
 {
     // docs
     $this->assertEquals(array(1, 2, 3), __u(array(1, 2, 3))->value());
 }
 public function testSize()
 {
     // from js
     $items = (object) array('one' => 1, 'two' => 2, 'three' => 3);
     $this->assertEquals(3, __u::size($items), 'can compute the size of an object');
     // extra
     $this->assertEquals(0, __u::size(array()));
     $this->assertEquals(1, __u::size(array(1)));
     $this->assertEquals(3, __u::size(array(1, 2, 3)));
     $this->assertEquals(6, __u::size(array(null, false, array(), array(1, 2, array('a', 'b')), 1, 2)));
     $this->assertEquals(3, __u(array(1, 2, 3))->size(), 'works with OO-style calls');
     // docs
     $stooge = new StdClass();
     $stooge->name = 'moe';
     $stooge->age = 40;
     $this->assertEquals(2, __u::size($stooge));
 }
 public function testRange()
 {
     // from js
     $this->assertEquals(array(), __u::range(0), 'range with 0 as a first argument generates an empty array');
     $this->assertEquals(array(0, 1, 2, 3), __u::range(4), 'range with a single positive argument generates an array of elements 0,1,2,...,n-1');
     $this->assertEquals(array(5, 6, 7), __u::range(5, 8), 'range with two arguments a & b, a<b generates an array of elements a,a+1,a+2,...,b-2,b-1');
     $this->assertEquals(array(), __u::range(8, 5), 'range with two arguments a & b, b<a generates an empty array');
     $this->assertEquals(array(3, 6, 9), __u::range(3, 10, 3), 'range with three arguments a & b & c, c < b-a, a < b generates an array of elements a,a+c,a+2c,...,b - (multiplier of a) < c');
     $this->assertEquals(array(3), __u::range(3, 10, 15), 'range with three arguments a & b & c, c > b-a, a < b generates an array with a single element, equal to a');
     $this->assertEquals(array(12, 10, 8), __u::range(12, 7, -2), 'range with three arguments a & b & c, a > b, c < 0 generates an array of elements a,a-c,a-2c and ends with the number not less than b');
     $this->assertEquals(array(0, -1, -2, -3, -4, -5, -6, -7, -8, -9), __u::range(0, -10, -1), 'final example in the Python docs');
     // extra
     $this->assertEquals(array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), __u::range(10));
     $this->assertEquals(array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), __u::range(1, 11));
     $this->assertEquals(array(0, 5, 10, 15, 20, 25), __u::range(0, 30, 5));
     $this->assertEquals(array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), __u(10)->range(), 'works in OO-style calls and 1 parameter');
     $this->assertEquals(array(10, 11, 12), __u(10)->range(13), 'works in OO-style calls and 2 parameters');
     $this->assertEquals(array(3, 6, 9), __u(3)->range(10, 3), 'works in OO-style calls and 3 parameters');
     // docs
     $this->assertEquals(array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), __u::range(10));
     $this->assertEquals(array(1, 2, 3, 4), __u::range(1, 5));
     $this->assertEquals(array(0, 5, 10, 15, 20, 25), __u::range(0, 30, 5));
     $this->assertEquals(array(0, -1, -2, -3, -4), __u::range(0, -5, -1));
     $this->assertEquals(array(), __u::range(0));
 }
 public function testEscape()
 {
     // from js
     $this->assertEquals('Curly &amp; Moe', __u::escape('Curly & Moe'));
     $this->assertEquals('Curly &amp;amp; Moe', __u::escape('Curly &amp; Moe'));
     // extra
     $this->assertEquals('Curly &amp; Moe', __u('Curly & Moe')->escape());
     $this->assertEquals('Curly &amp;amp; Moe', __u('Curly &amp; Moe')->escape());
 }
 public function testTap()
 {
     // from js
     $intercepted = null;
     $interceptor = function ($obj) use(&$intercepted) {
         $intercepted = $obj;
     };
     $returned = __u::tap(1, $interceptor);
     $this->assertEquals(1, $intercepted, 'passed tapped object to interceptor');
     $this->assertEquals(1, $returned, 'returns tapped object');
     $returned = __u(array(1, 2, 3))->chain()->map(function ($n) {
         return $n * 2;
     })->max()->tap($interceptor)->value();
     $this->assertTrue($returned === 6 && $intercepted === 6, 'can use tapped objects in a chain');
     $returned = __u::chain(array(1, 2, 3))->map(function ($n) {
         return $n * 2;
     })->max()->tap($interceptor)->value();
     $this->assertTrue($returned === 6 && $intercepted === 6, 'can use tapped objects in a chain with static call');
     // docs
     $interceptor = function ($obj) {
         return $obj * 2;
     };
     $result = __u(array(1, 2, 3))->chain()->max()->tap($interceptor)->value();
     $this->assertEquals(3, $result);
 }
 public function testAfter()
 {
     // from js
     $testAfter = function ($afterAmount, $timesCalled) {
         $afterCalled = 0;
         $after = __u::after($afterAmount, function () use(&$afterCalled) {
             $afterCalled++;
         });
         while ($timesCalled--) {
             $after();
         }
         return $afterCalled;
     };
     $this->assertEquals(1, $testAfter(5, 5), 'after(N) should fire after being called N times');
     $this->assertEquals(0, $testAfter(5, 4), 'after(N) should not fire unless called N times');
     $this->assertEquals(1, $testAfter(0, 0), 'after(0) should fire immediately');
     // extra
     $testAfterAgain = function ($afterAmount, $timesCalled) {
         $afterCalled = 0;
         $after = __u($afterAmount)->after(function () use(&$afterCalled) {
             $afterCalled++;
         });
         while ($timesCalled--) {
             $after();
         }
         return $afterCalled;
     };
     $this->assertEquals(1, $testAfterAgain(5, 5), 'after(N) should fire after being called N times in OO-style call');
     $this->assertEquals(0, $testAfterAgain(5, 4), 'after(N) should not fire unless called N times in OO-style call');
     // docs
     $str = '';
     $func = __u::after(3, function () use(&$str) {
         $str = 'x';
     });
     $func();
     $func();
     $func();
     $this->assertEquals('x', $str);
 }