diff --git a/inversify/inversify-tests.ts b/inversify/inversify-tests.ts
index 46b5cab97..c69bd064e 100644
--- a/inversify/inversify-tests.ts
+++ b/inversify/inversify-tests.ts
@@ -1,75 +1,200 @@
///
-interface FooInterface {
- name : string;
- greet() : string;
+import {
+ Kernel,
+ inject, tagged, named, paramNames,
+ IKernel, IKernelOptions, INewable,
+ IKernelModule, IFactory, IProvider, IRequest
+} from "inversify";
+
+module external_module_test {
+
+ interface INinja {
+ fight(): string;
+ sneak(): string;
+ }
+
+ interface IKatana {
+ hit(): string;
+ }
+
+ interface IShuriken {
+ throw();
+ }
+
+ class Katana implements IKatana {
+ public hit() {
+ return "cut!";
+ }
+ }
+
+ class Shuriken implements IShuriken {
+ public throw() {
+ return "hit!";
+ }
+ }
+
+ @inject("IKatana", "IShuriken")
+ class Ninja implements INinja {
+
+ private _katana: IKatana;
+ private _shuriken: IShuriken;
+
+ public constructor(katana: IKatana, shuriken: IShuriken) {
+ this._katana = katana;
+ this._shuriken = shuriken;
+ }
+
+ public fight() { return this._katana.hit(); };
+ public sneak() { return this._shuriken.throw(); };
+
+ }
+
+ let kernel = new Kernel();
+ kernel.bind("INinja").to(Ninja);
+ kernel.bind("IKatana").to(Katana);
+ kernel.bind("IShuriken").to(Shuriken).inSingletonScope();
+
+ let ninja = kernel.get("INinja");
+ console.log(ninja);
+
+ // Unbind
+ kernel.unbind("INinja");
+ kernel.unbindAll();
+
+ // Kernel modules
+ let module: IKernelModule = (k: IKernel) => {
+ k.bind("INinja").to(Ninja);
+ k.bind("IKatana").to(Katana).inTransientScope();
+ k.bind("IShuriken").to(Shuriken).inSingletonScope();
+ };
+
+ let options: IKernelOptions = {
+ middleware: [],
+ modules: [module]
+ };
+
+ kernel = new Kernel(options);
+ let ninja2 = kernel.get("INinja");
+ console.log(ninja2);
+
+ // binding types
+ kernel.bind("IKatana").to(Katana);
+ kernel.bind("IKatana").toValue(new Katana());
+
+ kernel.bind>("IKatana").toConstructor(Katana);
+
+ kernel.bind>("IKatana").toFactory((context) => {
+ return () => {
+ return kernel.get("IKatana");
+ };
+ });
+
+ kernel.bind>("IKatana").toAutoFactory();
+
+ kernel.bind>("IKatana").toProvider((context) => {
+ return () => {
+ return new Promise((resolve) => {
+ let katana = kernel.get("IKatana");
+ resolve(katana);
+ });
+ };
+ });
+
+ kernel.bind("IKatana").to(Katana).proxy((katanaToBeInjected: IKatana) => {
+ // BLOCK http://stackoverflow.com/questions/35906938/how-to-enable-harmony-proxies-in-gulp-mocha
+ /*
+ let handler = {
+ apply: function(target, thisArgument, argumentsList) {
+ console.log(`Starting: ${performance.now()}`);
+ let result = target.apply(thisArgument, argumentsList);
+ console.log(`Finished: ${performance.now()}`);
+ return result;
+ }
+ };
+ return new Proxy(katanaToBeInjected, handler);
+ */
+ return katanaToBeInjected;
+ });
+
+ interface IWeapon {}
+ interface ISamurai {
+ katana: IWeapon;
+ shuriken: IWeapon;
+ }
+
+ @inject("IWeapon", "IWeapon")
+ class Samurai implements ISamurai {
+ public katana: IWeapon;
+ public shuriken: IWeapon;
+ public constructor(
+ @tagged("canThrow", false) katana: IWeapon,
+ @tagged("canThrow", true) shuriken: IWeapon
+ ) {
+ this.katana = katana;
+ this.shuriken = shuriken;
+ }
+ }
+
+ kernel.bind("Samurai").to(Samurai);
+ kernel.bind("IWeapon").to(Katana).whenTargetTagged("canThrow", false);
+ kernel.bind("IWeapon").to(Shuriken).whenTargetTagged("canThrow", true);
+
+ let throwable = tagged("canThrow", true);
+ let notThrowable = tagged("canThrow", false);
+
+ @inject("IWeapon", "IWeapon")
+ class Samurai2 implements ISamurai {
+ public katana: IWeapon;
+ public shuriken: IWeapon;
+ public constructor(
+ @throwable("canThrow", false) katana: IWeapon,
+ @notThrowable("canThrow", true) shuriken: IWeapon
+ ) {
+ this.katana = katana;
+ this.shuriken = shuriken;
+ }
+ }
+
+ @inject("IWeapon", "IWeapon")
+ class Samurai3 implements ISamurai {
+ public katana: IWeapon;
+ public shuriken: IWeapon;
+ public constructor(
+ @named("strong") katana: IWeapon,
+ @named("weak") shuriken: IWeapon
+ ) {
+ this.katana = katana;
+ this.shuriken = shuriken;
+ }
+ }
+
+ kernel.bind("ISamurai").to(Samurai3);
+ kernel.bind("IWeapon").to(Katana).whenTargetNamed("strong");
+ kernel.bind("IWeapon").to(Shuriken).whenTargetNamed("weak");
+
+ @inject("IWeapon", "IWeapon")
+ @paramNames("katana", "shuriken")
+ class Samurai4 implements ISamurai {
+ public katana: IWeapon;
+ public shuriken: IWeapon;
+ public constructor(
+ katana: IWeapon,
+ shuriken: IWeapon
+ ) {
+ this.katana = katana;
+ this.shuriken = shuriken;
+ }
+ }
+
+ kernel.bind("ISamurai").to(Samurai4);
+
+ kernel.bind("IWeapon").to(Katana).when((request: IRequest) => {
+ return request.target.name.equals("katana");
+ });
+
+ kernel.bind("IWeapon").to(Shuriken).when((request: IRequest) => {
+ return request.target.name.equals("shuriken");
+ });
+
}
-
-interface BarInterface {
- name : string;
- greet() : string;
-}
-
-interface FooBarInterface {
- foo : FooInterface;
- bar : BarInterface;
- greet() : string;
-}
-
-class Foo implements FooInterface {
- public name : string;
- constructor() {
- this.name = "foo";
- }
- public greet() : string {
- return this.name;
- }
-}
-
-class Bar implements BarInterface {
- public name : string;
- constructor() {
- this.name = "bar";
- }
- public greet() : string {
- return this.name;
- }
-}
-
-class FooBar implements FooBarInterface {
- public foo : FooInterface;
- public bar : BarInterface;
- constructor(FooInterface : FooInterface, BarInterface : BarInterface) {
- this.foo = FooInterface;
- this.bar = BarInterface;
- }
- public greet() : string{
- return this.foo.greet() + this.bar.greet();
- }
-}
-
-// Kernel
-var kernel = new inversify.Kernel();
-
-// Identifiers
-var fooRuntimeIdentifier = "FooInterface";
-var barRuntimeIdentifier = "BarInterface";
-var fooBarRuntimeIdentifier = "FooBarInterface";
-
-// Bindings
-var fooBinding = new inversify.TypeBinding(fooRuntimeIdentifier, Foo);
-var barBinding = new inversify.TypeBinding(barRuntimeIdentifier, Bar);
-var fooBarBinding = new inversify.TypeBinding(fooBarRuntimeIdentifier, FooBar);
-
-kernel.bind(fooBinding);
-kernel.bind(barBinding);
-kernel.bind(fooBarBinding);
-
-// Resolve
-var foo = kernel.resolve(fooRuntimeIdentifier);
-var bar = kernel.resolve(barRuntimeIdentifier);
-var fooBar = kernel.resolve(fooBarRuntimeIdentifier);
-
-// Unbind
-kernel.unbind(fooRuntimeIdentifier);
-kernel.unbindAll();