diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..73e25df
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2010 Drew Bourne
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
\ No newline at end of file
diff --git a/asx/src/asx/array/range.as b/asx/src/asx/array/range.as
new file mode 100644
index 0000000..ccbe7fc
--- /dev/null
+++ b/asx/src/asx/array/range.as
@@ -0,0 +1,41 @@
+package asx.array
+{
+ import asx.fn.I;
+
+ /**
+ * Same as python range function.
+ *
+ * If only one arg is specified, start is zero, step is one and stop is the arg.
+ * Otherwise, args=start, stop, step.
+ * Negative stop and step can be used.
+ * Will throw ArgumentError if step is zero.
+ *
+ * @see http://docs.python.org/library/functions.html#range
+ */
+ public function range(...args):Array {
+ var start:int = 0;
+ var stop:int = 0;
+ var step:int = 1;
+
+ if (args.length == 1 ) {
+ stop = int(args[0]);
+ } else if (args.length > 1) {
+ start = int(args[0]);
+ stop = int(args[1]);
+ }
+ if (args.length == 3)
+ step = int(args[2]);
+
+ if (step == 0)
+ throw new ArgumentError("Step must not be null");
+
+ var p:Function = function(n:Number):Boolean {
+ return step > 0 ? n < stop : n > stop
+ };
+ var i:Function = function(n:Number):Number {
+ return n + step;
+ };
+
+ return unfold(start, p, I, i);
+ }
+}
\ No newline at end of file
diff --git a/asx/src/asx/fn/after.as b/asx/src/asx/fn/after.as
new file mode 100644
index 0000000..987935e
--- /dev/null
+++ b/asx/src/asx/fn/after.as
@@ -0,0 +1,19 @@
+package asx.fn
+{
+ /**
+ * Calls a Function then passes the original arguments and result to another Function.
+ *
+ * @param callingThis Function
+ * @param passArgsAndResultTo function(args:Array, result:*):*
+ * @result Function function(...args):*
+ */
+ public function after(callingThis:Function, passArgsAndResultTo:Function):Function
+ {
+ return function(...args):*
+ {
+ var result:* = callingThis.apply(null, args);
+ var modified:* = passArgsAndResultTo(args, result);
+ return modified === undefined ? result : modified;
+ }
+ }
+}
diff --git a/asx/src/asx/fn/before.as b/asx/src/asx/fn/before.as
new file mode 100644
index 0000000..50ab87f
--- /dev/null
+++ b/asx/src/asx/fn/before.as
@@ -0,0 +1,19 @@
+package asx.fn
+{
+ /**
+ * Calls a Function before calling another Function allowing the arguments to be modified.
+ *
+ * @param callingThis Function
+ * @param passArgsTo function(args:Array):*
+ * @result Function function(...args):*
+ */
+ public function before(callingThis:Function, passArgsTo:Function):Function
+ {
+ return function(...args):*
+ {
+ var modified:Array = passArgsTo(args);
+ var result:* = callingThis.apply(null, modified === undefined ? args : modified);
+ return result;
+ }
+ }
+}
\ No newline at end of file
diff --git a/asx/src/asx/fn/debounce.as b/asx/src/asx/fn/debounce.as
new file mode 100644
index 0000000..7d153ea
--- /dev/null
+++ b/asx/src/asx/fn/debounce.as
@@ -0,0 +1,33 @@
+package asx.fn
+{
+ import flash.events.TimerEvent;
+ import flash.utils.Timer;
+
+ /**
+ * Creates and returns a new debounced version of the passed function that
+ * will postpone its execution until after wait milliseconds have elapsed
+ * since the last time it was invoked.
+ *
+ * @param fn
+ * @param millisecondsToWait
+ */
+ public function debounce(fn:Function, millisecondsToWait:Number):Function
+ {
+ var timer:Timer = new Timer(millisecondsToWait, 1);
+ var listener:Function;
+
+ return function(...args):void {
+ if (listener !== null) {
+ timer.removeEventListener(TimerEvent.TIMER_COMPLETE, listener);
+ }
+
+ listener = function(event:TimerEvent):void {
+ fn.apply(null, args);
+ }
+
+ timer.addEventListener(TimerEvent.TIMER_COMPLETE, listener);
+ timer.reset();
+ timer.start();
+ };
+ }
+}
\ No newline at end of file
diff --git a/asx/src/asx/fn/defer.as b/asx/src/asx/fn/defer.as
new file mode 100644
index 0000000..3c63dd6
--- /dev/null
+++ b/asx/src/asx/fn/defer.as
@@ -0,0 +1,17 @@
+package asx.fn
+{
+ import flash.utils.setTimeout;
+
+ /**
+ * Defers invoking the function to the next execution cycle.
+ *
+ * @example
+ *
+ * defer(function():void { ... });
+ *
+ */
+ public function defer(fn:Function):void
+ {
+ setTimeout(fn, 0);
+ }
+}
\ No newline at end of file
diff --git a/asx/src/asx/fn/throttle.as b/asx/src/asx/fn/throttle.as
new file mode 100644
index 0000000..400de67
--- /dev/null
+++ b/asx/src/asx/fn/throttle.as
@@ -0,0 +1,23 @@
+package asx.fn
+{
+ import flash.utils.getTimer;
+
+ /**
+ * Creates a new function that when invoked repeatedly will only call the
+ * original function at most once within every millisecondsToWait.
+ *
+ * @param fn Function to throttle
+ * @param millisecondsToWait Milliseconds to wait.
+ */
+ public function throttle(fn:Function, millisecondsToWait:Number):Function
+ {
+ var lastTime:int = 0;
+ return function(...args):void {
+ var thisTime:int = getTimer();
+ if ((thisTime - lastTime) > millisecondsToWait) {
+ fn.apply(null, args);
+ lastTime = thisTime;
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/asx/src/asx/object/clear.as b/asx/src/asx/object/clear.as
new file mode 100644
index 0000000..a882046
--- /dev/null
+++ b/asx/src/asx/object/clear.as
@@ -0,0 +1,25 @@
+package asx.object
+{
+ /**
+ * Clears all the items from an Array, or keys from an Object or Dictionary, returning the given object.
+ *
+ * @param object Array, Object or Dictionary to clear;
+ */
+ public function clear(object:Object):*
+ {
+ if (object is Array)
+ {
+ var array:Array = object as Array;
+ array.splice(0, array.length);
+ }
+ else
+ {
+ for (var key:* in object)
+ {
+ delete object[key];
+ }
+ }
+
+ return object;
+ }
+}
\ No newline at end of file
diff --git a/asx/src/asx/object/keys.as b/asx/src/asx/object/keys.as
new file mode 100644
index 0000000..4d953ce
--- /dev/null
+++ b/asx/src/asx/object/keys.as
@@ -0,0 +1,26 @@
+package asx.object
+{
+ /**
+ * Returns the iterable keys from an Object.
+ *
+ * @param object Object to extract keys from.
+ * @returns Array of keys, empty Array if no values.
+ *
+ * @example
+ *
+ * trace(keys({ one: 1, two: 2, three: 3 });
+ * // one two three
+ *
+ */
+ public function keys(object:Object):Array
+ {
+ var result:Array = [];
+
+ for (var key:* in object)
+ {
+ result[result.length] = key;
+ }
+
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/asx/src/asx/object/merge.as b/asx/src/asx/object/merge.as
index 10ce9c4..4ad14ee 100644
--- a/asx/src/asx/object/merge.as
+++ b/asx/src/asx/object/merge.as
@@ -1,18 +1,22 @@
-package asx.object {
-
- /**
- * Merge enumerable fields from b -> a, returns a
- *
- * @param a Target
- * @param b Source
- * @return a
- */
- public function merge(a:Object, b:Object):Object {
-
- for (var field:String in b) {
- a[field] = b[field];
- }
-
- return a;
- }
+package asx.object
+{
+ /**
+ * Merge enumerable fields from sources -> target, returns target.
+ *
+ * @param target Target Object to populate with keys and values.
+ * @param ...source Source objects to retrieve keys and values from.
+ * @return target
+ */
+ public function merge(target:Object, ...sources):*
+ {
+ for each (var source:* in sources)
+ {
+ for (var field:String in source)
+ {
+ target[field] = source[field];
+ }
+ }
+
+ return target;
+ }
}
diff --git a/asx/src/asx/object/values.as b/asx/src/asx/object/values.as
new file mode 100644
index 0000000..e95e9c9
--- /dev/null
+++ b/asx/src/asx/object/values.as
@@ -0,0 +1,26 @@
+package asx.object
+{
+ /**
+ * Returns the iterable values from an Object.
+ *
+ * @param object Object to extract values from.
+ * @returns Array of values, empty Array if no values.
+ *
+ * @example
+ *
+ * trace(values({ one: 1, two: 2, three: 3 });
+ * // 1 2 3
+ *
+ */
+ public function values(object:Object):Array
+ {
+ var result:Array = [];
+
+ for each (var value:* in object)
+ {
+ result[result.length] = value;
+ }
+
+ return result;
+ }
+}
\ No newline at end of file
diff --git a/asx_test/src/asx/array/RangeTest.as b/asx_test/src/asx/array/RangeTest.as
new file mode 100644
index 0000000..fd8becb
--- /dev/null
+++ b/asx_test/src/asx/array/RangeTest.as
@@ -0,0 +1,72 @@
+package asx.array
+{
+ import mx.collections.ArrayCollection;
+
+ import org.flexunit.assertThat;
+ import org.hamcrest.collection.array;
+ import org.hamcrest.object.equalTo;
+
+ public class RangeTest
+ {
+
+ [Test]
+ public function range_oneArg_returnsSequencialArray_fromZeroToStop():void
+ {
+ assertThat(range(10), array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9));
+ }
+
+ [Test]
+ public function range_twoArgs_returnsSequencialArray_fromStartToStop():void
+ {
+ assertThat(range(1,11), array(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+ }
+
+ [Test]
+ public function range_twoArgs_stepNotMultipleOfStep_returnsSequencialArray_endsBeforeStop():void
+ {
+ assertThat(range(0, 4, 3), array(0, 3));
+ }
+
+ [Test]
+ public function range_threeArgs_returnsSequencialArray_fromStartToStop_byStep_even():void
+ {
+ assertThat(range(0, 30, 5), array(0, 5, 10, 15, 20, 25));
+ }
+
+ [Test]
+ public function range_threeArgs_returnsSequencialArray_fromStartToStop_byStep_odd():void
+ {
+ assertThat(range(0, 10, 3), array(0, 3, 6, 9));
+ }
+
+ [Test]
+ public function range_threeArgs_negativeStopAndStep_returnsSequencialArray_fromStartToStop():void
+ {
+ assertThat(range(0, -10, -1), array(0, -1, -2, -3, -4, -5, -6, -7, -8, -9));
+ }
+
+ [Test]
+ public function range_twoArgs_positiveStart_negativeStep_returnsSequentialArray_fromStartToStop():void
+ {
+ assertThat(range(5, 0, -1), array(5, 4, 3, 2, 1));
+ }
+
+ [Test]
+ public function range_oneArgs_zeroStop_returnsEmptyArray():void
+ {
+ assertThat(range(0), array());
+ }
+
+ [Test]
+ public function range_twoArgs_positiveStep_largerStopThanStart_returnsEmptyArray():void
+ {
+ assertThat(range(1, 0), array());
+ }
+
+ [Test(expects="ArgumentError")]
+ public function range_zero_throwsArgumentError():void
+ {
+ range(0, 1, 0);
+ }
+ }
+}
\ No newline at end of file
diff --git a/asx_test/src/asx/fn/AfterTest.as b/asx_test/src/asx/fn/AfterTest.as
new file mode 100644
index 0000000..7e94093
--- /dev/null
+++ b/asx_test/src/asx/fn/AfterTest.as
@@ -0,0 +1,60 @@
+package asx.fn
+{
+ import asx.array.map;
+
+ import org.flexunit.assertThat;
+ import org.hamcrest.collection.*;
+ import org.hamcrest.core.*;
+ import org.hamcrest.object.*;
+
+ public class AfterTest
+ {
+ [Test]
+ public function after_should_pass_args_to_afterFunction():void
+ {
+ var items:Array = [1, 2, 3];
+ var afterArgs:Array = [];
+
+ var result:Array = map(items, after(function(item:Number):Number { return item * 2; },
+ function(args:Array, _:Number):void { afterArgs.push(args[0]) }));
+
+ assertThat("result", result, array(2, 4, 6));
+ assertThat("afterArgs", afterArgs, array(1, 2, 3));
+ }
+
+ [Test]
+ public function after_should_pass_result_to_afterFunction():void
+ {
+ var items:Array = [1, 2, 3];
+ var afterResults:Array = [];
+
+ var result:Array = map(items, after(function(item:Number):Number { return item * 2; },
+ function(_:Array, result:Number):void { afterResults.push(result) }));
+
+ assertThat("result", result, array(2, 4, 6));
+ assertThat("afterResults", afterResults, array(2, 4, 6));
+ }
+
+ [Test]
+ public function after_should_return_result_from_afterFunction():void
+ {
+ var items:Array = [1, 2, 3];
+
+ var result:Array = map(items, after(function(item:Number):Number { return item * 2; },
+ function(_:Array, result:Number):Number { return result * 3 }));
+
+ assertThat("result", result, array(6, 12, 18));
+ }
+
+ [Test]
+ public function after_should_ignore_undefined_result_from_afterFunction():void
+ {
+ var items:Array = [1, 2, 3];
+
+ var result:Array = map(items, after(function(item:Number):Number { return item * 2; },
+ function(_:Array, __:Number):* { return undefined; }));
+
+ assertThat("result", result, array(2, 4, 6));
+ }
+ }
+}
diff --git a/asx_test/src/asx/fn/BeforeTest.as b/asx_test/src/asx/fn/BeforeTest.as
new file mode 100644
index 0000000..384b107
--- /dev/null
+++ b/asx_test/src/asx/fn/BeforeTest.as
@@ -0,0 +1,47 @@
+package asx.fn
+{
+ import asx.array.map;
+
+ import org.flexunit.assertThat;
+ import org.hamcrest.collection.*;
+ import org.hamcrest.core.*;
+ import org.hamcrest.object.*;
+
+ public class BeforeTest
+ {
+ [Test]
+ public function before_should_pass_args_to_beforeFunction():void
+ {
+ var items:Array = [1, 2, 3];
+ var beforeArgs:Array = [];
+
+ var result:Array = map(items, before(function(item:Number):Number { return item * 2; },
+ function(args:Array):void { beforeArgs.push(args[0]) }));
+
+ assertThat("result", result, array(2, 4, 6));
+ assertThat("beforeArgs", beforeArgs, array(1, 2, 3));
+ }
+
+ [Test]
+ public function before_should_pass_modified_args_to_original_function():void
+ {
+ var items:Array = [1, 2, 3];
+
+ var result:Array = map(items, before(function(item:Number):Number { return item * 2; },
+ function(args:Array):Array { return [args[0] * 3] }));
+
+ assertThat("result", result, array(6, 12, 18));
+ }
+
+ [Test]
+ public function before_should_ignore_modified_args_from_before_function_when_undefined():void
+ {
+ var items:Array = [1, 2, 3];
+
+ var result:Array = map(items, before(function(item:Number):Number { return item * 2; },
+ function(args:Array):void { false; }));
+
+ assertThat("result", result, array(2, 4, 6));
+ }
+ }
+}
diff --git a/asx_test/src/asx/fn/DebounceTest.as b/asx_test/src/asx/fn/DebounceTest.as
new file mode 100644
index 0000000..52ad9f2
--- /dev/null
+++ b/asx_test/src/asx/fn/DebounceTest.as
@@ -0,0 +1,35 @@
+package asx.fn
+{
+ import flash.events.EventDispatcher;
+ import flash.events.EventDispatcher;
+ import flash.events.Event;
+ import flash.events.TimerEvent;
+ import flash.utils.getTimer;
+ import flash.utils.Timer;
+
+ import org.flexunit.async.Async;
+ import org.flexunit.assertThat;
+ import org.hamcrest.object.equalTo;
+ import org.hamcrest.object.isFalse;
+ import org.hamcrest.number.greaterThan;
+
+ public class DebounceTest
+ {
+ [Test(async)]
+ public function invokes_the_original_function_after_debounced_function_stops_being_called_for_wait_milliseconds():void
+ {
+ var dispatcher:EventDispatcher = new EventDispatcher();
+ Async.proceedOnEvent(this, dispatcher, Event.COMPLETE, 1500);
+
+ var start:int = getTimer();
+ var complete:Function = function():void {
+ assertThat(getTimer() - start, greaterThan(700));
+ dispatcher.dispatchEvent(new Event(Event.COMPLETE));
+ };
+
+ var timer:Timer = new Timer(50, 8);
+ timer.addEventListener(TimerEvent.TIMER, debounce(complete, 300));
+ timer.start();
+ }
+ }
+}
\ No newline at end of file
diff --git a/asx_test/src/asx/fn/DeferTest.as b/asx_test/src/asx/fn/DeferTest.as
new file mode 100644
index 0000000..8404322
--- /dev/null
+++ b/asx_test/src/asx/fn/DeferTest.as
@@ -0,0 +1,29 @@
+package asx.fn
+{
+ import flash.events.IEventDispatcher;
+ import flash.events.EventDispatcher;
+ import flash.events.Event;
+
+ import org.flexunit.async.Async;
+ import org.flexunit.assertThat;
+ import org.hamcrest.object.isFalse;
+
+ public class DeferTest
+ {
+ [Test(async)]
+ public function defer_should_execute_async():void
+ {
+ var dispatcher:IEventDispatcher = new EventDispatcher();
+ Async.proceedOnEvent(this, dispatcher, Event.COMPLETE, 10);
+
+ var called:Boolean = false;
+
+ defer(function():void {
+ called = true;
+ dispatcher.dispatchEvent(new Event(Event.COMPLETE));
+ });
+
+ assertThat("should not have called yet", called, isFalse());
+ }
+ }
+}
\ No newline at end of file
diff --git a/asx_test/src/asx/fn/TapTest.as b/asx_test/src/asx/fn/TapTest.as
new file mode 100644
index 0000000..60c3a24
--- /dev/null
+++ b/asx_test/src/asx/fn/TapTest.as
@@ -0,0 +1,23 @@
+package asx.fn
+{
+ public class TapTest
+ {
+ [Test]
+ public function tap_should_forward_arguments_to_initial_function():void
+ {
+
+ }
+
+ [Test]
+ public function tap_should_return_result_from_initial_function():void
+ {
+
+ }
+
+ [Test]
+ public function tap_should_():void
+ {
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/asx_test/src/asx/fn/ThrottleTest.as b/asx_test/src/asx/fn/ThrottleTest.as
new file mode 100644
index 0000000..f198d97
--- /dev/null
+++ b/asx_test/src/asx/fn/ThrottleTest.as
@@ -0,0 +1,34 @@
+package asx.fn
+{
+ import flash.events.TimerEvent;
+ import flash.utils.getTimer;
+ import flash.utils.Timer;
+
+ import org.flexunit.async.Async;
+ import org.flexunit.assertThat;
+ import org.hamcrest.core.allOf;
+ import org.hamcrest.object.equalTo;
+ import org.hamcrest.number.greaterThan;
+ import org.hamcrest.number.lessThan;
+
+ public class ThrottleTest
+ {
+ [Test(async)]
+ public function invokes_the_original_function_at_most_once_within_the_given_window_of_time():void
+ {
+ var start:int = getTimer();
+ var invoked:int = 0;
+ var throttled:Function = throttle(function():void { invoked++; }, 200);
+
+ var timer:Timer = new Timer(40, 6);
+ timer.addEventListener(TimerEvent.TIMER, function(event:TimerEvent):void { throttled(); });
+
+ Async.handleEvent(this, timer, TimerEvent.TIMER_COMPLETE, function(event:TimerEvent, unused:Object):void {
+ assertThat("should be delayed", getTimer() - start, allOf(greaterThan(240), lessThan(280)));
+ assertThat("should be invoked twice within the window of time", invoked, equalTo(2));
+ });
+
+ timer.start();
+ }
+ }
+}
\ No newline at end of file
diff --git a/asx_test/src/asx/object/ClearTest.as b/asx_test/src/asx/object/ClearTest.as
new file mode 100644
index 0000000..7681475
--- /dev/null
+++ b/asx_test/src/asx/object/ClearTest.as
@@ -0,0 +1,41 @@
+package asx.object
+{
+ import flash.utils.Dictionary;
+
+ import org.flexunit.assertThat;
+ import org.hamcrest.collection.emptyArray;
+ import org.hamcrest.object.strictlyEqualTo;
+
+ public class ClearTest
+ {
+ [Test]
+ public function should_clear_array_items():void
+ {
+ var items:Array = [1, 2, 3];
+ var cleared:Array = clear(items);
+
+ assertThat(cleared, strictlyEqualTo(items));
+ assertThat(cleared, emptyArray());
+ }
+
+ [Test]
+ public function should_clear_anonymous_object_keys():void
+ {
+ var object:Object = { one: 1, two: 2, three: 3 };
+ var cleared:Object = clear(object);
+
+ assertThat(cleared, strictlyEqualTo(object));
+ assertThat(keys(cleared), emptyArray());
+ }
+
+ [Test]
+ public function should_clear_Dictionary_keys():void
+ {
+ var dict:Dictionary = merge(new Dictionary(), { one: 1, two: 2, three: 3 });
+ var cleared:Dictionary = clear(dict);
+
+ assertThat(cleared, strictlyEqualTo(dict));
+ assertThat(keys(cleared), emptyArray());
+ }
+ }
+}
diff --git a/asx_test/src/asx/object/KeysTest.as b/asx_test/src/asx/object/KeysTest.as
new file mode 100644
index 0000000..d4e53cb
--- /dev/null
+++ b/asx_test/src/asx/object/KeysTest.as
@@ -0,0 +1,41 @@
+package asx.object
+{
+ import flash.utils.Dictionary;
+
+ import org.flexunit.assertThat;
+ import org.hamcrest.collection.emptyArray;
+ import org.hamcrest.collection.hasItems;
+
+ public class KeysTest
+ {
+ [Test]
+ public function should_return_all_iterable_keys_of_anonymous_object():void
+ {
+ assertThat(keys({ one:1, two:2, three:3 }), hasItems('one', 'two', 'three'));
+ }
+
+ [Test]
+ public function should_return_all_iterable_keys_of_Dictionary():void
+ {
+ var dict:Dictionary = new Dictionary();
+ dict['one'] = 1;
+ dict['two'] = 2;
+ dict['three'] = 3;
+ assertThat(keys(dict), hasItems('one', 'two', 'three'));
+ }
+
+ [Test]
+ public function should_not_return_keys_for_class_instance():void
+ {
+ var inst:Instance = new Instance();
+ assertThat(keys(inst), emptyArray());
+ }
+ }
+}
+
+internal class Instance
+{
+ public var one:int = 1;
+ public var two:int = 2;
+ public var three:int = 3;
+}
\ No newline at end of file
diff --git a/asx_test/src/asx/object/MergeTest.as b/asx_test/src/asx/object/MergeTest.as
new file mode 100644
index 0000000..87b4702
--- /dev/null
+++ b/asx_test/src/asx/object/MergeTest.as
@@ -0,0 +1,65 @@
+package asx.object
+{
+ import flash.utils.Dictionary;
+
+ import org.flexunit.assertThat;
+ import org.hamcrest.object.hasProperties;
+ import org.hamcrest.object.strictlyEqualTo;
+
+ public class MergeTest
+ {
+ [Test]
+ public function should_merge_keys_and_values_from_anonymous_object_to_target_object():void
+ {
+ var target:Object = { one: 1, two: 2 };
+ var source:Object = { two: 22, three: 3 };
+
+ var result:Object = merge(target, source);
+
+ assertThat(result, strictlyEqualTo(target));
+ assertThat(result, hasProperties({ one: 1, two: 22, three: 3 }));
+ }
+
+ [Test]
+ public function should_merge_keys_and_values_from_anonymous_object_to_target_Dictionary():void
+ {
+ var target:Dictionary = new Dictionary();
+ target['one'] = 1;
+ target['two'] = 2;
+
+ var source:Object = { two: 22, three: 3 };
+
+ var result:Dictionary = merge(target, source);
+
+ assertThat(result, strictlyEqualTo(target));
+ assertThat(result, hasProperties({ one: 1, two: 22, three: 3 }));
+ }
+
+ [Test]
+ public function should_merge_keys_and_values_from_Dictionary_to_target_Dictionary():void
+ {
+ var target:Dictionary = new Dictionary();
+ target['one'] = 1;
+ target['two'] = 2;
+
+ var source:Dictionary = new Dictionary();
+ target['two'] = 22;
+ target['three'] = 3;
+
+ var result:Dictionary = merge(target, source);
+
+ assertThat(result, strictlyEqualTo(target));
+ assertThat(result, hasProperties({ one: 1, two: 22, three: 3 }));
+ }
+
+ [Test]
+ public function should_merge_multiple_sources_to_target():void
+ {
+ var target:Dictionary = new Dictionary();
+ var result:Dictionary = merge(target, { one: 1 }, { two: 2, three: 3 }, { two: 22, four: 4 });
+
+ assertThat(result, strictlyEqualTo(target));
+ assertThat(result, hasProperties({ one: 1, two: 22, three: 3, four: 4 }));
+ }
+ }
+}
\ No newline at end of file
diff --git a/asx_test/src/asx/object/ValuesTest.as b/asx_test/src/asx/object/ValuesTest.as
new file mode 100644
index 0000000..6227bc9
--- /dev/null
+++ b/asx_test/src/asx/object/ValuesTest.as
@@ -0,0 +1,41 @@
+package asx.object
+{
+ import flash.utils.Dictionary;
+
+ import org.flexunit.assertThat;
+ import org.hamcrest.collection.emptyArray;
+ import org.hamcrest.collection.hasItems;
+
+ public class ValuesTest
+ {
+ [Test]
+ public function should_return_all_iterable_values_of_anonymous_object():void
+ {
+ assertThat(values({ one:1, two:2, three:3 }), hasItems(1, 2, 3));
+ }
+
+ [Test]
+ public function should_return_all_iterable_values_of_Dictionary():void
+ {
+ var dict:Dictionary = new Dictionary();
+ dict['one'] = 1;
+ dict['two'] = 2;
+ dict['three'] = 3;
+ assertThat(values(dict), hasItems(1, 2, 3));
+ }
+
+ [Test]
+ public function should_not_return_values_for_class_instance():void
+ {
+ var inst:Instance = new Instance();
+ assertThat(values(inst), emptyArray());
+ }
+ }
+}
+
+internal class Instance
+{
+ public var one:int = 1;
+ public var two:int = 2;
+ public var three:int = 3;
+}
\ No newline at end of file
diff --git a/asx_test/src/asx_test.mxml b/asx_test/src/asx_test.mxml
index f4db0fd..d372688 100644
--- a/asx_test/src/asx_test.mxml
+++ b/asx_test/src/asx_test.mxml
@@ -1,14 +1,18 @@
diff --git a/build.sh b/build.sh
index 54e969d..18141c4 100755
--- a/build.sh
+++ b/build.sh
@@ -1,16 +1,25 @@
+# ASX FlexUnit Runner
+mxmlc asx_test/src/asx_test.mxml \
+-output=asx_test/bin/asx_test.swf \
+-debug=true \
+-sp+=asx/src \
+-sp+=asx_test/src \
+-library-path+=asx_test/libs
+
# ASX SpecRunner
-mxmlc specs/AsxSpecRunner.mxml \
- -output=bin/AsxSpecs.swf \
- -debug=true \
- -sp specs \
- -sp src \
- -sp ../spectacular-as3/src/ \
- -sp ../hamcrest-as3/hamcrest/src \
+# mxmlc specs/AsxSpecRunner.mxml \
+# -output=bin/AsxSpecs.swf \
+# -debug=true \
+# -sp specs \
+# -sp src \
+# -sp ../spectacular-as3/src/ \
+# -sp ../hamcrest-as3/hamcrest/src \
# swc
compc \
- -include-sources src \
- -output bin/asx.swc
+-sp+=asx/src \
+-include-sources asx/src \
+-output asx/bin/asx.swc
# generate docs
# asdoc \