示例#1
1
 public Gateway(string gatewayServer,bool server)
 {
     Console.WriteLine("did " + gatewayServer);
     channels = new Dictionary<string, GatewayMessage>();
     if (server) {
         var jv = new JsDictionary<string, bool>();
         jv["force new connection"] = true;
         GatewaySocket = Global.Require<SocketIOClient>("socket.io-client").AConnect(gatewayServer, jv);
     } else {        
         GatewaySocket = SocketIOClient.Connect(gatewayServer);
     }
     GatewaySocket.On<SocketClientMessageModel>("Client.Message", data => channels[data.Channel](data.User, data.Content));
     GatewaySocket.On<string>("disconnect", data => Console.WriteLine("Disconnected "+ DateTime.Now));
 }
示例#2
0
      public PhoneListController(Scope _scope, Http _http)
      {
         what = "main";         

         /*
         http.Get("hello.html").Success((data,status)=> {
            Window.Alert(data.ToString());
         }).Error((data,status)=>{ 
            Window.Alert("errore!");
         });
         */

         var risp = _http.Get("data.json");

         risp.Success((data,status,header)=> 
         {            
            person = (JsDictionary) data;
           // Window.Alert(person["name"].ToString());
         });

         risp.Error((data,status)=>
         { 
         //   Window.Alert("errore!");
         });                
      }
示例#3
0
		public static void PopulateFrom(this Record data, JsDictionary source)
		{
			var d = (JsDictionary)data;
			foreach (var p in source) {
				if (d.ContainsKey(p.Key)) d[p.Key]=p.Value;
			}
		}
示例#4
0
        /*public QueueMessage(Dictionary dict) : base((dict ?? (Dictionary)new object()))
         {
             
         }*/

        public Consumer(JsDictionary obj)
        {
            var tf = ( (JsDictionary) (object) this );
            foreach (var v in obj.Keys) {
                tf[v] = obj[v];
            }
        }
            private void EnsureInitialized() {
                if (configObject == null)
                    return;

				var npTypes = (string[])configObject["pluginNodeProcessors"];
				var tmTypes = (JsDictionary)configObject["pluginTypedMarkupParsers"];
				var umTypes = (string[])configObject["pluginUntypedMarkupParsers"];

				pluginNodeProcessors       = new INodeProcessor[npTypes.Length];
				pluginTypedMarkupParsers   = new Dictionary<string, ITypedMarkupParserImpl>();
				pluginUntypedMarkupParsers = new IUntypedMarkupParserImpl[umTypes.Length];

				for (int i = 0; i < npTypes.Length; i++) {
					pluginNodeProcessors[i] = (INodeProcessor)Container.CreateObjectByTypeName(npTypes[i]);
				}
				foreach (var tm in tmTypes) {
					pluginTypedMarkupParsers[tm.Key] = (ITypedMarkupParserImpl)Container.CreateObjectByTypeName((string)tm.Value);
				}
				for (int i = 0; i < umTypes.Length; i++) {
					pluginUntypedMarkupParsers[i] = (IUntypedMarkupParserImpl)Container.CreateObjectByTypeName(umTypes[i]);
				}

			    docProcessor = new DocumentProcessor(pluginNodeProcessors, new TypedMarkupParser(pluginTypedMarkupParsers), new UntypedMarkupParser(pluginUntypedMarkupParsers));

                configObject = null;
            }
		public void GetEnumeratorWorks() {
			var d = JsDictionary.GetDictionary(new { a = "valueA", b = 134 });
			var d2 = new JsDictionary();
			foreach (var kvp in d) {
				d2[kvp.Key] = kvp.Value;
			}
			Assert.AreEqual(d, d2);
		}
示例#7
0
 private void handler(HttpRequest request, HttpResponse response)
 {
     var dict = new JsDictionary();
     dict["Content-Type"] = "text/html";
     if (oldIndex.Count > 0) {
         response.WriteHead(200, dict);
         var inj = ( siteIndex++ ) % oldIndex.Count;
         response.End(oldIndex[inj]);
     } else {
         response.WriteHead(200, dict);
         response.End();
     }
 }
		/// <summary>
		/// On the server, an easier way to obtain a parser is through the SaltarelleParserFactory class.
		/// </summary>
		public SaltarelleParser(INodeProcessor[] pluginNodeProcessors, IDictionary<string, ITypedMarkupParserImpl> pluginTypedMarkupParsers, IUntypedMarkupParserImpl[] pluginUntypedMarkupParsers) {
			#if CLIENT
				JsDictionary cfg = JsDictionary.GetDictionary(pluginNodeProcessors);
				if (!Script.IsNullOrUndefined(cfg) && cfg.ContainsKey("pluginNodeProcessors")) {
				    // We have an [AlternateSignature] constructor which can cause us to be called with a config object instead of real parameters
                    configObject = cfg;
                    return;
				}
			#endif
			docProcessor = new DocumentProcessor(pluginNodeProcessors, new TypedMarkupParser(pluginTypedMarkupParsers), new UntypedMarkupParser(pluginUntypedMarkupParsers));
			this.pluginNodeProcessors       = pluginNodeProcessors ?? new INodeProcessor[0];
			this.pluginTypedMarkupParsers   = pluginTypedMarkupParsers ?? new Dictionary<string, ITypedMarkupParserImpl>();
			this.pluginUntypedMarkupParsers = pluginUntypedMarkupParsers ?? new IUntypedMarkupParserImpl[0];
		}
示例#9
0
        /// <summary>
        /// Use to add local text to dictionary
        /// </summary>
        /// <param name="obj">Object with local text list in a format like Enums:{WeekDays:{Monday: 'Pazartesi', ... }}} to
        /// "Enums.WeekDays.Monday" = "Pazartesi"</param>
        /// <param name="prefix">Prefix to add to all keys</param>
        /// <remarks>Obj is provided in a compact format to keep size as small as possible.</remarks>
        public static void Add(JsDictionary<string, object> obj, string prefix)
        {
            if (!Script.IsValue(obj))
                return;

            prefix = prefix ?? "";

            foreach (var k in obj.As<JsDictionary>().Keys)
            {
                var actual = prefix + k;
                var o = obj[k];
                if (Script.TypeOf(o) == "object")
                    Add(o.As<JsDictionary>(), actual + ".");
                else
                    table[actual] = o.As<string>();
            }
        }
示例#10
0
        private void handler(HttpRequest request, HttpResponse response)
        {
            fs.ReadFile(__dirname + "/blank.html",
                        "ascii",
                        (err, content) => {
                            var fieldSets = "";
                            fieldSets += string.Format("<span>Main Site: {0}</span>", string.Format("<a href='#{0}' onclick='goHere(\"{1}\",\"MainSite\");'>Launch</a>", (int.Parse((Math.Random() * 20000).ToString())), Constants.HomeAddress));

                            fieldSets += buildFieldset(sites, "Site Servers");
                            fieldSets += buildFieldset(gateways, "Gateway Servers");
                            fieldSets += buildFieldset(games, "Game Servers");
                            fieldSets += buildFieldset(debugs, "Debug Servers");
                            fieldSets += buildFieldset(chats, "Chat Servers");
                            fieldSets += buildFieldset(chats, "Chat Servers");

                            var dict = new JsDictionary();
                            dict["Content-Type"] = "text/html";
                            response.WriteHead(200, dict);
                            response.End(content.Replace("{0}", fieldSets).Replace("{1}", Constants.HomeAddress));
                        });
        }
示例#11
0
    public void SpecRunner()
    {
        /**
         Jasmine is a behavior-driven development framework for testing JavaScript code. It does not depend on any other JavaScript frameworks. It does not require a DOM. And it has a clean, obvious syntax so that you can easily write tests.

         This guide is running against Jasmine version <span class="version">FILLED IN AT RUNTIME</span>.
         */

        /**
         ## Suites: `describe` Your Tests

         A test suite begins with a call to the global Jasmine function `describe` with two parameters: a string and a function. The string is a name or title for a spec suite - usually what is under test. The function is a block of code that implements the suite.

         ## Specs

         Specs are defined by calling the global Jasmine function `it`, which, like `describe` takes a string and a function. The string is a title for this spec and the function is the spec, or test. A spec contains one or more expectations that test the state of the code under test.

         An expectation in Jasmine is an assertion that can be either true or false. A spec with all true expectations is a passing spec. A spec with one or more expectations that evaluate to false is a failing spec.
         */
        describe("A suite", () =>
        {
            it("contains spec with an expectation", () =>
            {
                expect(true).toBe(true);
            });
        });

        /**
         ### It's Just Functions

         Since `describe` and `it` blocks are functions, they can contain any executable code necessary to implement the test. JavaScript scoping rules apply, so variables declared in a `describe` are available to any `it` block inside the suite.
         */
        describe("A suite is just a function", () =>
        {
            bool a;

            it("and so is a spec", () =>
            {
                a = true;

                expect(a).toBe(true);
            });
        });

        /**
         ## Expectations

         Expectations are built with the function `expect` which takes a value, called the actual. It is chained with a Matcher function, which takes the expected value.
         */
        describe("The 'toBe' matcher compares with ===", () =>
        {
            /**
             ### Matchers

             Each matcher implements a boolean comparison between the actual value and the expected value. It is responsible for reporting to Jasmine if the expectation is true or false. Jasmine will then pass or fail the spec.
             */

            it("and has a positive case ", () =>
            {
                expect(true).toBe(true);
            });

            /**
             Any matcher can evaluate to a negative assertion by chaining the call to `expect` with a `not` before calling the matcher.

             */

            it("and can have a negative case", () =>
            {
                expect(false).not.toBe(true);
            });
        });

        /**
         ### Included Matchers

         Jasmine has a rich set of matchers included. Each is used here - all expectations and specs pass.

         There is also the ability to write [custom matchers](https://github.com/pivotal/jasmine/wiki/Matchers) for when a project's domain calls for specific assertions that are not included below.
         */

        describe("Included matchers:", () =>
        {

            it("The 'toBe' matcher compares with ===", () =>
            {
                int a = 12;
                int b = a;

                expect(a).toBe(b);
                expect(a).not.toBe(null);
            });

            describe("The 'toEqual' matcher", () =>
            {

                it("works for simple literals and variables", () =>
                {
                    int a = 12;
                    expect(a).toEqual(12);
                });

                it("should work for objects", () =>
                {
                    JsDictionary<string, int> foo = new JsDictionary<string, int>();
                    JsDictionary<string, int> bar = new JsDictionary<string, int>();
                    foo["a"] = 12;
                    foo["b"] = 34;
                    bar["a"] = 12;
                    bar["b"] = 34;
                    expect(foo).toEqual(bar);
                });
            });

            it("The 'toMatch' matcher is for regular expressions", () =>
            {
                string message = "foo bar baz";

                //expect(message).toMatch(/bar/);       // regex literal expressions do not exist in C#
                expect(message).toMatch("bar");
                //expect(message).not.toMatch(/quux/);  // regex literal expressions do not exist in C#
            });

            it("The 'toBeDefined' matcher compares against `undefined`", () =>
            {
                JsDictionary<string, string> a = new JsDictionary<string, string>();
                a["foo"] = "foo";

                expect(a["foo"]).toBeDefined();
                expect((object)((dynamic)a).bar).not.toBeDefined();    // dynamic so that you can call a.bar from C#
            });

            it("The `toBeUndefined` matcher compares against `undefined`", () =>
            {
                JsDictionary<string, string> a = new JsDictionary<string, string>();
                a["foo"] = "foo";

                expect(a["foo"]).not.toBeUndefined();
                expect((object)((dynamic)a).bar).toBeUndefined();
            });

            it("The 'toBeNull' matcher compares against null", () =>
            {
                string a = null;
                string foo = "foo";

                expect(null).toBeNull();
                expect(a).toBeNull();
                expect(foo).not.toBeNull();
            });

            it("The 'toBeTruthy' matcher is for boolean casting testing", () =>
            {
                string a = null;
                string foo = "foo";

                expect(foo).toBeTruthy();
                expect(a).not.toBeTruthy();
            });

            it("The 'toBeFalsy' matcher is for boolean casting testing", () =>
            {
                string a = null;
                string foo = "foo";

                expect(a).toBeFalsy();
                expect(foo).not.toBeFalsy();
            });

            it("The 'toContain' matcher is for finding an item in an Array", () =>
            {
                string[] a = new string[] { "foo", "bar", "baz" };

                expect(a).toContain("bar");
                expect(a).not.toContain("quux");
            });

            it("The 'toBeLessThan' matcher is for mathematical comparisons", () =>
            {
                double pi = 3.1415926;
                double e = 2.78;

                expect(e).toBeLessThan(pi);
                expect(pi).not.toBeLessThan(e);
            });

            it("The 'toBeGreaterThan' is for mathematical comparisons", () =>
            {
                double pi = 3.1415926;
                double e = 2.78;

                expect(pi).toBeGreaterThan(e);
                expect(e).not.toBeGreaterThan(pi);
            });

            it("The 'toBeCloseTo' matcher is for precision math comparison", () =>
            {
                double pi = 3.1415926;
                double e = 2.78;

                expect(pi).not.toBeCloseTo(e, 2);
                expect(pi).toBeCloseTo(e, 0);
            });

            it("The 'toThrow' matcher is for testing if a function throws an exception", () =>
            {
                Func<int> foo = () =>
                {
                    return 1 + 2;
                };
                Func<int> bar = () =>
                {
                    throw new Exception("err!");
                    return 1 + 1;
                };

                expect(foo).not.toThrow();
                expect(bar).toThrow();
            });
        });

        /**
         ## Grouping Related Specs with `describe`

         The `describe` function is for grouping related specs. The string parameter is for naming the collection of specs, and will be concatenated with specs to make a spec's full name. This aids in finding specs in a large suite. If you name them well, your specs read as full sentences in traditional [BDD][bdd] style.

         [bdd]: http://en.wikipedia.org/wiki/Behavior-driven_development
         */
        describe("A spec", () =>
        {
            it("is just a function, so it can contain any code", () =>
            {
                int foo = 0;
                foo += 1;

                expect(foo).toEqual(1);
            });

            it("can have more than one expectation", () =>
            {
                int foo = 0;
                foo += 1;

                expect(foo).toEqual(1);
                expect(true).toEqual(true);
            });
        });

        /**
         ### Setup and Teardown

         To help a test suite DRY up any duplicated setup and teardown code, Jasmine provides the global `beforeEach` and `afterEach` functions. As the name implies the `beforeEach` function is called once before each spec in the `describe` is run and the `afterEach` function is called once after each spec.

         Here is the same set of specs written a little differently. The variable under test is defined at the top-level scope -- the `describe` block --  and initialization code is moved into a `beforeEach` function. The `afterEach` function resets the variable before continuing.

         */

        describe("A spec (with setup and tear-down)", () =>
        {
            int foo = 0;

            beforeEach(() =>
            {
                foo = 0;
                foo += 1;
            });

            afterEach(() =>
            {
                foo = 0;
            });

            it("is just a function, so it can contain any code", () =>
            {
                expect(foo).toEqual(1);
            });

            it("can have more than one expectation", () =>
            {
                expect(foo).toEqual(1);
                expect(true).toEqual(true);
            });
        });

        /**
         ### Nesting `describe` Blocks

         Calls to `describe` can be nested, with specs defined at any level. This allows a suite to be composed as a tree of functions. Before a spec is executed, Jasmine walks down the tree executing each `beforeEach` function in order. After the spec is executed, Jasmine walks through the `afterEach` functions similarly.

         */
        describe("A spec", () =>
        {
            int foo = 0;

            beforeEach(() =>
            {
                foo = 0;
                foo += 1;
            });

            afterEach(() =>
            {
                foo = 0;
            });

            it("is just a function, so it can contain any code", () =>
            {
                expect(foo).toEqual(1);
            });

            it("can have more than one expectation", () =>
            {
                expect(foo).toEqual(1);
                expect(true).toEqual(true);
            });

            describe("nested inside a second describe", () =>
            {
                int bar = 0;

                beforeEach(() =>
                {
                    bar = 1;
                });

                it("can reference both scopes as needed ", () =>
                {
                    expect(foo).toEqual(bar);
                });
            });
        });

        /**
         ## Disabling Specs and Suites

         Suites and specs can be disabled with the `xdescribe` and `xit` functions, respectively. These suites and specs are skipped when run and thus their results will not appear in the results.

         */
        xdescribe("A spec", () =>
        {
            int foo = 0;

            beforeEach(() =>
            {
                foo = 0;
                foo += 1;
            });

            xit("is just a function, so it can contain any code", () =>
            {
                expect(foo).toEqual(1);
            });
        });

        /**
        ## Pending Specs
        Pending specs do not run, but their names will show up in the results as `pending`.
        */
        //TODO: Pending() doesn't work in PhantomJS
        describe("Pending specs", () =>
        {
            /** Any spec declared with `xit` is marked as pending.
             */
            xit("can be declared 'xit'", () =>
            {
                expect(true).toBe(false);
            });

            /** Any spec declared without a function body will also be marked pending in results.
             */

            it("can be declared with 'it' but without a function");

            /** And if you call the function `pending` anywhere in the spec body, no matter the expectations, the spec will be marked pending.
             */
            it("can be declared by calling 'pending' in the spec body", () =>
            {                
                expect(true).toBe(false);                
                pending("this is why it is pending");
            });
        });

        /**
         ## Spies

         Jasmine's test doubles are called spies. A spy can stub any function and tracks calls to it and all arguments. There are special matchers for interacting with spies.

         The `toHaveBeenCalled` matcher will return true if the spy was called. The `toHaveBeenCalledWith` matcher will return true if the argument list matches any of the recorded calls to the spy.
         */

        // TODO object containing a function
        describe("A spy", () =>
        {
            JsDictionary<string, Action<string>> foo = new JsDictionary<string, Action<string>>();
            foo["setBar"] = null;
            string bar = null;
            Spy spy = null;

            beforeEach(() =>
            {

                foo["setBar"] = (value) =>
                {
                    bar = value;
                };

                spy = spyOn(foo, "setBar");

                foo["setBar"]("123");
                foo["setBar"]("456");
            });

            it("tracks that the spy was called", () =>
            {
                expect(foo["setBar"]).toHaveBeenCalled();
            });

            it("tracks its number of calls", () =>
            {
                expect(spy.calls.count()).toEqual(2);
            });

            it("tracks all the arguments of its calls", () =>
            {
                expect(spy).toHaveBeenCalledWith("123");
            });

            it("allows access to the most recent call", () =>
            {
                expect(spy.calls.mostRecent().Args[0]).toEqual("456");
            });

            it("allows access to other calls", () =>
            {
                expect(spy.calls.all()[0].Args[0]).toEqual("123");
            });

            it("stops all execution on a function", () =>
            {
                expect(bar).toBeNull();
            });
        });


        /**
         ### Spies: `and.callThrough`

         By chaining the spy with `and.callThrough`, the spy will still track all calls to it but in addition it will delegate to the actual implementation.
         */

        // TODO object containing a function
        describe("A spy, when configured to call through", () =>
        {
            JsDictionary foo = new JsDictionary();
            foo["setBar"] = null;
            foo["getBar"] = null;
            string bar = null;
            string fetchedBar = null;
            Spy spy = null;

            beforeEach(() =>
            {
                foo["setBar"] = new Action<string>((value) =>
                {
                    bar = value;
                });
                foo["getBar"] = new Func<string>(() => bar);

                spy = spyOn(foo, "getBar").and.callThrough();

                ((Action<string>)foo["setBar"])("123");
                fetchedBar = ((Func<string>)foo["getBar"])();
            });

            it("tracks that the spy was called", () =>
            {
                expect(spy).toHaveBeenCalled();
            });

            it("should not effect other functions", () =>
            {
                expect(bar).toEqual("123");
            });

            it("when called returns the requested value", () =>
            {
                expect(fetchedBar).toEqual("123");
            });
        });


        /**
         ### Spies: `and.returnValue`

         By chaining the spy with `and.returnValue`, all calls to the function will return a specific value.
         */
        // TODO object containing a function
        describe("A spy, when faking a return value", () =>
        {
            JsDictionary foo = new JsDictionary();
            foo["setBar"] = null;
            foo["getBar"] = null;
            string bar = null;
            string fetchedBar = null;
            Spy spy = null;

            beforeEach(() =>
            {
                foo["setBar"] = new Action<string>((value) =>
                {
                    bar = value;
                });
                foo["getBar"] = new Func<string>(() => bar);

                spy = spyOn(foo, "getBar").and.returnValue("745");

                ((Action<string>)foo["setBar"])("123");
                fetchedBar = ((Func<string>)foo["getBar"])();
            });

            it("tracks that the spy was called", () =>
            {
                expect(spy).toHaveBeenCalled();
            });

            it("should not effect other functions", () =>
            {
                expect(bar).toEqual("123");
            });

            it("when called returns the requested value", () =>
            {
                expect(fetchedBar).toEqual("745");
            });
        });


        /**
         ### Spies: `and.callFake`

         By chaining the spy with `and.callFake`, all calls to the spy will delegate to the supplied function.
         */
        // TODO objects containing functions
        describe("A spy, when faking a function", () =>
        {
            JsDictionary foo = new JsDictionary();
            foo["setBar"] = null;
            foo["getBar"] = null;
            string bar = null;
            string fetchedBar = null;
            Spy spy = null;

            beforeEach(() =>
            {

                foo["setBar"] = new Action<string>((value) =>
                {
                    bar = value;
                });
                foo["getBar"] = new Func<string>(() => bar);

                spy = spyOn(foo, "getBar").and.callFake((Function)(new Func<string>(() => "1001")));

                ((Action<string>)foo["setBar"])("123");
                fetchedBar = ((Func<string>)foo["getBar"])();
            });

            it("tracks that the spy was called", () =>
            {
                expect(spy).toHaveBeenCalled();
            });

            it("should not effect other functions", () =>
            {
                expect(bar).toEqual("123");
            });

            it("when called returns the requested value", () =>
            {
                expect(fetchedBar).toEqual("1001");
            });
        });

        /**
        ### Spies: `and.throwError`
        By chaining the spy with `and.throwError`, all calls to the spy will `throw` the specified value as an error.
        */
        describe("A spy, when configured to throw an error", () =>
        {
            JsDictionary<string, Action<string>> foo = new JsDictionary<string, Action<string>>();
            foo["setBar"] = null;
            string bar = null;

            beforeEach(() =>
            {
                foo["setBar"] = (value) =>
                {
                    bar = value;
                };

                spyOn(foo, "setBar").and.throwError("quux");
            });

            it("throws the value", () =>
            {
                expect(new Action(() =>
                {
                    foo["setBar"]("123");
                })).toThrowError("quux");
            });
        });


        /**
        ### Spies: `and.stub`
        When a calling strategy is used for a spy, the original stubbing behavior can be returned at any time with `and.stub`.
        */
        describe("A spy", () =>
        {
            JsDictionary<string, Action<double?>> foo = new JsDictionary<string, Action<double?>>();
            foo["setBar"] = null;
            double? bar = null;
            Spy spy = null;

            beforeEach(() =>
            {
                foo["setBar"] = (value) =>
                {
                    bar = value;
                };

                spy = spyOn(foo, "setBar").and.callThrough();
            });

            it("can call through and then stub in the same spec", () =>
            {
                foo["setBar"](123);
                expect(bar).toEqual(123);

                spy.and.stub();
                bar = null;

                foo["setBar"](123);
                expect(bar).toBe(null);
            });
        });

        /**
        ### Other tracking properties

        Every call to a spy is tracked and exposed on the `calls` property.
        */
        describe("A spy", () =>
        {

            JsDictionary<string, Action<double?>> foo = new JsDictionary<string, Action<double?>>();
            foo["setBar"] = null;
            double? bar = null;
            Spy fooSetBar = null;

            beforeEach(() =>
            {
                foo["setBar"] = (value) =>
                {
                    bar = value;
                };

                fooSetBar = spyOn(foo, "setBar");
            });

            /**
             * `.calls.any()`: returns `false` if the spy has not been called at all, and then `true` once at least one call happens.
             */
            it("tracks if it was called at all", () =>
            {
                expect(fooSetBar.calls.any()).toEqual(false);

                foo["setBar"](0);

                expect(fooSetBar.calls.any()).toEqual(true);
            });

            /**
             * `.calls.count()`: returns the number of times the spy was called
             */
            it("tracks the number of times it was called", () =>
            {
                expect(fooSetBar.calls.count()).toEqual(0);

                foo["setBar"](0);
                foo["setBar"](0);

                expect(fooSetBar.calls.count()).toEqual(2);
            });

            /**
             * `.calls.argsFor(index)`: returns the arguments passed to call number `index`
             */
            it("tracks the arguments of each call", () =>
            {
                foo["setBar"](123);
                foo["setBar"](456);

                expect(fooSetBar.calls.argsFor(0)).toEqual(new[] { 123 });
                expect(fooSetBar.calls.argsFor(1)).toEqual(new[] { 456 });
            });

            /**
             * `.calls.allArgs()`: returns the arguments to all calls
             */
            it("tracks the arguments of all calls", () =>
            {
                foo["setBar"](123);
                foo["setBar"](456);

                expect(fooSetBar.calls.allArgs()).toEqual(new[] { new[] { 123 }, new[] { 456 } });
            });

            /**
             * `.calls.all()`: returns the context (the `this`) and arguments passed all calls
             */
            it("can provide the context and arguments to all calls", () =>
            {
                foo["setBar"](123);

                expect(fooSetBar.calls.all()).toEqual(new[] { new { @object = foo, args = new[] { 123 }, returnValue = Script.Undefined } });
            });

            /**
             * `.calls.mostRecent()`: returns the context (the `this`) and arguments for the most recent call
             */
            it("has a shortcut to the most recent call", () =>
            {
                foo["setBar"](123);
                foo["setBar"](456);

                expect(fooSetBar.calls.mostRecent()).toEqual(new { @object = foo, args = new[] { 456 }, returnValue = Script.Undefined });
            });

            /**
             * `.calls.first()`: returns the context (the `this`) and arguments for the first call
             */
            it("has a shortcut to the first call", () =>
            {
                foo["setBar"](123);
                foo["setBar"](456);

                expect(fooSetBar.calls.first()).toEqual(new { @object = foo, args = new[] { 123 }, returnValue = Script.Undefined });
            });

            /**
             * When inspecting the return from `all()`, `mostRecent()` and `first()`, the `object` property is set to the value of `this` when the spy was called.
             */
            it("tracks the context", () =>
            {
                Spy spy = createSpy("spy");

                JsDictionary<string, Spy> baz = new JsDictionary<string, Spy>();
                JsDictionary<string, Spy> quux = new JsDictionary<string, Spy>();

                baz["fn"] = spy;
                quux["fn"] = spy;
                baz["fn"].Call(123);
                quux["fn"].Call(456);

                expect(spy.calls.first().Object).toBe(baz);
                expect(spy.calls.mostRecent().Object).toBe(quux);
            });

            /**
             * `.calls.reset()`: clears all tracking for a spy
             */
            it("can be reset", () =>
            {
                foo["setBar"](123);
                foo["setBar"](456);

                expect(fooSetBar.calls.any()).toBe(true);

                fooSetBar.calls.reset();

                expect(fooSetBar.calls.any()).toBe(false);
            });
        });

        /**
         ### Spies: `createSpy`

         When there is not a function to spy on, `jasmine.createSpy` can create a "bare" spy. This spy acts as any other spy - tracking calls, arguments, etc. But there is no implementation behind it. Spies are JavaScript objects and can be used as such.

         */
        describe("A spy, when created manually", () =>
        {
            Spy whatAmI = null;

            beforeEach(() =>
            {
                whatAmI = createSpy("whatAmI");

                whatAmI.Call("I", "am", "a", "spy");
            });

            it("is named, which helps in error reporting", () =>
            {
                expect(whatAmI.and.identity()).toEqual("whatAmI");
            });

            it("tracks that the spy was called", () =>
            {
                expect(whatAmI).toHaveBeenCalled();
            });

            it("tracks its number of calls", () =>
            {
                expect(whatAmI.calls.count()).toEqual(1);
            });

            it("tracks all the arguments of its calls", () =>
            {
                expect(whatAmI).toHaveBeenCalledWith("I", "am", "a", "spy");
            });

            it("allows access to the most recent call", () =>
            {
                expect(whatAmI.calls.mostRecent().Args[0]).toEqual("I");
            });
        });

        /**
         ### Spies: `createSpyObj`

         In order to create a mock with multiple spies, use `jasmine.createSpyObj` and pass an array of strings. It returns an object that has a property for each string that is a spy.
         */
        describe("Multiple spies, when created manually", () =>
        {
            dynamic tape = null;

            beforeEach(() =>
            {
                tape = createSpyObj("tape", new string[] { "play", "pause", "stop", "rewind" });

                tape.play();
                tape.pause();
                tape.rewind(0);
            });

            it("creates spies for each requested function", () =>
            {
                expect((object)tape.play).toBeDefined();
                expect((object)tape.pause).toBeDefined();
                expect((object)tape.stop).toBeDefined();
                expect((object)tape.rewind).toBeDefined();
            });

            it("tracks that the spies were called", () =>
            {
                expect((object)tape.play).toHaveBeenCalled();
                expect((object)tape.pause).toHaveBeenCalled();
                expect((object)tape.rewind).toHaveBeenCalled();
                expect((object)tape.stop).not.toHaveBeenCalled();
            });

            it("tracks all the arguments of its calls", () =>
            {
                expect((object)tape.rewind).toHaveBeenCalledWith(0);
            });
        });

        /**
         ## Matching Anything with `jasmine.any`

         `jasmine.any` takes a constructor or "class" name as an expected value. It returns `true` if the constructor matches the constructor of the actual value.
         */

        // TODO any matcher
        describe("jasmine.any", () =>
        {
            it("matches any value", () =>
            {
                expect(null).toEqual(any(typeof(object)));
                expect(12).toEqual(any(typeof(double)));
            });

            describe("when used with a spy", () =>
            {
                it("is useful for comparing arguments", () =>
                {
                    Spy foo = createSpy("foo");
                    foo.Call(12, new Func<bool>(() => true));

                    expect(foo).toHaveBeenCalledWith(any(typeof(double)), any(typeof(Function)));
                });
            });
        });

        /**
         ## Partial Matching with `jasmine.objectContaining`
         `jasmine.objectContaining` is for those times when an expectation only cares about certain key/value pairs in the actual.
         */

        describe("jasmine.objectContaining", () =>
        {
            JsDictionary foo = new JsDictionary();

            foo["a"] = 0;
            foo["b"] = 0;
            foo["bar"] = "";

            beforeEach(() =>
            {

                foo["a"] = 1;
                foo["b"] = 2;
                foo["bar"] = "baz";
            });

            it("matches objects with the expect key/value pairs", () =>
            {
                expect(foo).toEqual(objectContaining(new
                {
                    bar = "baz"
                }));
                expect(foo).not.toEqual(objectContaining(new
                {
                    c = 37
                }));
            });

            describe("when used with a spy", () =>
            {
                it("is useful for comparing arguments", () =>
                {
                    Spy callback = createSpy("callback");

                    callback.Call(new
                    {
                        bar = "baz"
                    });

                    expect(callback).toHaveBeenCalledWith(objectContaining(new
                    {
                        bar = "baz"
                    }));
                    expect(callback).not.toHaveBeenCalledWith(objectContaining(new
                    {
                        c = 37
                    }));
                });
            });
        });


        /**
         ## Mocking the JavaScript Clock

         The Jasmine Mock Clock is available for a test suites that need the ability to use `setTimeout` or `setInterval` callbacks. It makes the timer callbacks synchronous, thus making them easier to test.

         */
        // TODO clock
        describe("Manually ticking the Jasmine Mock Clock", () =>
        {
            Spy timerCallback = null;

            //
            // It is installed with a call to `jasmine.Clock.useMock` in a spec or suite that needs to call the timer functions.
            //
            beforeEach(() =>
            {
                timerCallback = createSpy("timerCallback");
                clock().install();
            });

            afterEach(() =>
            {
                timerCallback = createSpy("timerCallback");
                clock().uninstall();
            });

            //
            // Calls to any registered callback are triggered when the clock is ticked forward via the `jasmine.Clock.tick` function, which takes a number of milliseconds.
            //
            it("causes a timeout to be called synchronously", () =>
            {
                Window.SetTimeout(() =>
                {
                    timerCallback.Call();
                }, 100);



                expect(timerCallback).not.toHaveBeenCalled();

                clock().tick(101);

                expect(timerCallback).toHaveBeenCalled();
            });

            it("causes an interval to be called synchronously", () =>
            {
                Window.SetInterval(() =>
                {
                    timerCallback.Call();
                }, 100);

                expect(timerCallback).not.toHaveBeenCalled();

                clock().tick(101);
                expect(timerCallback.calls.count()).toEqual(1);

                clock().tick(50);
                expect(timerCallback.calls.count()).toEqual(1);

                clock().tick(50);
                expect(timerCallback.calls.count()).toEqual(2);
            });
        });


        /**
         ## Asynchronous Support
         __This syntax has changed for Jasmine 2.0.__
         Jasmine also has support for running specs that require testing asynchronous operations.
         */
        describe("Asynchronous specs", () =>
        {
            double value = 0;
            /**
             Calls to `beforeEach`, `it`, and `afterEach` can take an optional single argument that should be called when the async work is complete.
             */
            beforeEach((done) =>
            {
                Window.SetTimeout(() =>
                {
                    value = 0;
                    done();
                }, 1000);
            });

            /**
             This spec will not start until the `done` function is called in the call to `beforeEach` above. And this spec will not complete until its `done` is called.
             */

            it("should support async execution of test preparation and expectations", (done) =>
            {
                value++;
                expect(value).toBeGreaterThan(0);

                Task.Delay(1).ContinueWith((T) =>
                {
                    value = 1;
                    expect(value).toBeGreaterThan(0);
                    done();
                });
            });

            /**
             By default jasmine will wait for 5 seconds for an asynchronous spec to finish before causing a timeout failure.
             If specific specs should fail faster or need more time this can be adjusted by setting `jasmine.DEFAULT_TIMEOUT_INTERVAL` around them.

             If the entire suite should have a different timeout, `jasmine.DEFAULT_TIMEOUT_INTERVAL` can be set globally, outside of any given `describe`.
             */           
            describe("long asynchronous specs", () =>
            {
                double originalTimeout = 0;
                beforeEach(() =>
                {
                    originalTimeout = DEFAULT_TIMEOUT_INTERVAL;
                    DEFAULT_TIMEOUT_INTERVAL = 1000;
                });

                it("takes a long time", (done) =>
                {
                    Window.SetTimeout(() =>
                    {
                        done();
                    }, 900);
                });

                afterEach(() =>
                {
                    DEFAULT_TIMEOUT_INTERVAL = originalTimeout;
                });
            });

            /**
             By default jasmine will wait for 5 seconds for an asynchronous spec to finish before causing a timeout failure.
             If specific specs should fail faster or need more time this can be adjusted by passing a timeout value to it, etc.

             If the entire suite should have a different timeout, `jasmine.DEFAULT_TIMEOUT_INTERVAL` can be set globally, outside of any given `describe`.
             */           
            describe("long asynchronous specs with explicit timeout parameter", () =>
            {               
                beforeEach((done) => 
                {
                    done();
                }, 1000);

                it("takes a long time", (done) =>
                {
                    Window.SetTimeout(() =>
                    {
                        done();
                    }, 900);
                });

                afterEach((done) =>
                {
                    done();
                }, 1000);
            });
        });


        /**
         *
         * Often a project will want to encapsulate custom matching code for use across multiple specs. Here is how to create a Jasmine-compatible custom matcher.
         *
         * A custom matcher at its root is a comparison function that takes an `actual` value and `expected` value. This factory is passed to Jasmine, ideally in a call to `beforeEach` and will be in scope and available for all of the specs inside a given call to `describe`. Custom matchers are torn down between specs. The name of the factory will be the name of the matcher exposed on the return value of the call to `expect`.
         *
         */


        /**
        * ## Matcher Factories
        *
        * Custom matcher factories are passed two parameters: `util`, which has a set of utility functions for matchers to use (see: [`matchersUtil.js`][mu.js] for the current list) and `customEqualityTesters` which needs to be passed in if `util.equals` is ever called. These parameters are available for use when then matcher is called.
        *
        * [mu.js]: https://github.com/pivotal/jasmine/blob/master/src/core/matchers/matchersUtil.js
        */
        /**
        * The factory method should return an object with a `compare` function that will be called to check the expectation.
        */

        /**
         * This object has a custom matcher named "toBeGoofy".
         */
        JsDictionary<string, CustomMatcherComparer> customMatchers = new JsDictionary<string, CustomMatcherComparer>();
        customMatchers["toBeGoofy"] = CustomMatchers.ToBeGoofy;


        /**
        * ### Custom negative comparators
        *
        * If you need more control over the negative comparison (the `not` case) than the simple boolean inversion above, you can also have your matcher factory include another key, `negativeCompare` alongside `compare`, for which the value is a function to invoke when `.not` is used. This function/key is optional.
        */

        /**
         * ## Registration and Usage
         */
        describe("Custom matcher: 'toBeGoofy'", () =>
        {
            /**
             * Register the custom matchers with Jasmine. All properties on the object passed in will be available as custom matchers (e.g., in this case `toBeGoofy`).
             */
            beforeEach(() =>
            {
                addMatchers(customMatchers);
            });

            /**
             * Once a custom matcher is registered with Jasmine, it is available on any expectation.
             */
            it("is available on an expectation", () =>
            {
                expect(new
                {
                    hyuk = "gawrsh"
                }).toBeGoofy();
            });

            it("can take an 'expected' parameter", () =>
            {
                expect(new
                {
                    hyuk = "gawrsh is fun"
                }).toBeGoofy(" is fun");
            });

            it("can be negated", () =>
            {
                expect(new
                {
                    hyuk = "this is fun"
                }).not.toBeGoofy();
            });
        });

        describe("Custom matcher: 'toBeDivisibleBy'", () =>
        {
            beforeEach(() =>
            {
                addMatcher("toBeDivisibleBy", CustomMatchers.ToBeDivisibleBy);
            });

            it("is available on an expectation", () =>
            {
                expect(7).toBeDivisibleBy(7);
            });

            it("can be negated", () =>
            {
                expect(8).not.toBeDivisibleBy(7);
            });
        });

        /**
        * ## Custom Equality Testers
        */
        describe("custom equality", () =>
        {
            /**
             * You can customize how jasmine determines if two objects are equal by defining your own custom equality testers.
             * A custom equality tester is a function that takes two arguments.
             */
            Func<string, string, bool> myCustomEquality = (first, second) =>
            {
                /**
                 * If the custom equality tester knows how to compare the two items, it should return either true or false
                 */

                if (Script.TypeOf(first) == "string" && Script.TypeOf(second) == "string")
                {
                    return first[0] == second[1];
                }

                return false;

                /**
                 * Otherwise, it should return undefined, to tell jasmine's equality tester that it can't compare the items
                 */
            };

            /**
             * Then you register your tester in a `beforeEach` so jasmine knows about it.
             */
            beforeEach(() =>
            {
                addCustomEqualityTester(myCustomEquality);
            });

            /**
             * Then when you do comparisons in a spec, custom equality testers will be checked first before the default equality logic.
             */
            it("should be custom equal", () =>
            {
                expect("abc").toEqual("aaa");
            });

            /**
             * If your custom tester returns false, no other equality checking will be done.
             */
            it("should be custom not equal", () =>
            {
                expect("abc").not.toEqual("abc");
            });
        });

        /**
         *
         * If you don't like the way the built-in jasmine reporters look, you can always write your own.
         *
         */

        /**
         * A jasmine reporter is just an object with the right functions available.
         * None of the functions here are required when creating a custom reporter, any that are not specified on your reporter will just be ignored.
         */

        IJsApiReporter myReporter = new newReporter();

        /**
            * Register the reporter with jasmine
            */
        getEnv().addReporter(myReporter);

        /**
         * If you look at the console output for this page, you should see the output from this reporter
         */
        describe("Top Level suite", () =>
        {
            it("spec", () =>
            {
                expect(1).toBe(1);
            });

            describe("Nested suite", () =>
            {
                it("nested spec", () =>
                {
                    expect(true).toBe(true);
                });
            });
        });

        describe("Publicly exposed classes", () =>
        {
            it("can instantiate publicly exposed jasmine classes", () =>
            {
                expect(new Action(() =>
                {
                    Any a = new Any(typeof(Object));
                    Spy s = new Spy("mySpy");
                    Spy s2 = new Spy();
                    Suite suite = new Suite(new {});
                    CallTracker ct = new CallTracker();
                    Clock c = new Clock(new object{}, new {}, null);
                    ObjectContaining oc = new ObjectContaining(new {propA = 5});
                    Spec spec = new Spec(new { queueableFn = new {} });
                    Env e = new Env(new object{});
                    SpyStrategy sc = new SpyStrategy(new {});
                })).not.toThrow();
            });

            it("can extend publicly exposed jasmine classes", () =>
            {
                expect(new Action(() =>
                {
                    AnyPlus ap = new AnyPlus(typeof(String));
                    ap.Test();
                    ClockPlus cp = new ClockPlus(new object{}, new object{}, null);
                    cp.Test();
                    ObjectContainingPlus ocp = new ObjectContainingPlus(new object{});
                    ocp.Test();
                    SuitePlus sp = new SuitePlus(new { });
                    sp.Test();
                    SpecPlus spp = new SpecPlus(new { queueableFn = new { } });
                    spp.Test();
                    EnvPlus ep = new EnvPlus(new { });
                    ep.Test();
                    CallTrackerPlus ctp = new CallTrackerPlus();
                    ctp.Test();
                    SpyStrategyPlus ssp = new SpyStrategyPlus(new { });
                    ssp.Test();
                })).not.toThrow();
            });
        });

        /**
         * Focusing specs will make it so that they are the only specs that run.
         * NOTE: These tests have to be commented out so the rest of the tests actually run!
         */
        //describe("Focused specs", () => {

        //    /** Any spec declared with `fit` is focused.
        //     */
        //    fit("is focused and will run", () => {
        //        expect(true).toBeTruthy();
        //    });

        //    it("is not focused and will not run", () =>{
        //        expect(true).toBeFalsy();
        //    });

        //    /** You can focus on a `describe` with `fdescribe`
        //     *
        //     */
        //    fdescribe("focused describe", () =>{
        //        it("will run", () =>{
        //            expect(true).toBeTruthy();
        //        });

        //        it("will also run", () =>{
        //            expect(true).toBeTruthy();
        //        });
        //    });

        //    /** If you nest focused and unfocused specs inside `fdescribes`, only focused specs run.
        //     *
        //     */
        //    fdescribe("another focused describe", () =>{
        //        fit("is focused and will run", () => {
        //            expect(true).toBeTruthy();
        //        });

        //        it("is not focused and will not run", () =>{
        //            expect(true).toBeFalsy();
        //        });
        //    });
        //});

    }
示例#12
0
		protected virtual void InitConfig(JsDictionary config) {
			id    = (string)config["id"];
			title = (string)config["title"];
			Attach();
		}
 public static void AddClassRules(string name, JsDictionary rules)
 {
 }
 public static void AddClassRules(JsDictionary rules)
 {
 }
示例#15
0
 public void ToArrayWorks()
 {
     var other = new JsDictionary();
     other["length"] = 2;
     other["0"] = "a";
     other["1"] = "b";
     var actual = Array.ToArray(other);
     Assert.IsTrue(actual is Array);
     Assert.AreEqual(actual, new[] { "a", "b" });
 }
示例#16
0
 public void bind(JsDictionary events) {}      
示例#17
0
		protected virtual void InitConfig(JsDictionary config) {
			id = (string)config["id"];
			tabCaptions = (string[])config["tabCaptions"];
			position = (Position)config["position"];
			selectedTab = (int)config["selectedTab"];
			rightAlignTabs = (bool)config["rightAlignTabs"];
			Attach();
		}
 public virtual void SetParams(JsDictionary editorParams)
 {
 }
示例#19
0
		protected virtual void InitConfig(JsDictionary config) {
			id                 = (string)config["id"];
			width              = (int)config["width"];
			height             = (int)config["height"];
			tabIndex           = (int)config["tabIndex"];
			hasChecks          = (bool)config["hasChecks"];
			enabled            = (bool)config["enabled"];
			invisibleRoot      = (TreeNode)config["invisibleRoot"];
			enableDragDrop     = (bool)config["enableDragDrop"];
			autoCheckHierarchy = (bool)config["autoCheckHierarchy"];
			nextNodeId         = (int)config["nextNodeId"];

			FixTreeAfterDeserialize(invisibleRoot);
			invisibleRoot.treeIfRoot = this;
			invisibleRoot.parent     = null;
			
			int[] selectionPath = (int[])config["selectionPath"];
			selectedNode = selectionPath != null ? FollowTreeNodePath(invisibleRoot, selectionPath) : null;

			Attach();
		}
示例#20
0
 /// <summary>
 /// Attaches a handler for handling the specified event once on the matched set of elements.
 /// </summary>
 /// <param name="eventName">The name of the event.</param>
 /// <param name="eventData">Any data that needs to be passed to the event handler.</param>
 /// <param name="eventHandler">The event handler to be invoked.</param>
 /// <returns></returns>
 public jElement one(string eventName, JsDictionary eventData, jQueryEventHandlerWithContext eventHandler) {
     return null;
 }
示例#21
0
 public static object GetValue(Widget editor)
 {
     var target = new JsDictionary();
     SaveValue(editor, dummy, target);
     return target["_"];
 }
示例#22
0
 /// <summary>
 /// Attaches an event handler function for one or more events to the selected elements.
 /// </summary>
 /// <param name="eventsMap">A dictionary in which the string keys represent the event names, and the values represent the handler for that event.</param>
 /// <returns>The current jElement</returns>
 public jElement on(JsDictionary eventsMap) {
     return null;
 }
示例#23
0
 /// <summary>
 /// Attaches an event handler function for one or more events to the selected elements.
 /// </summary>
 /// <param name="eventsMap">A dictionary in which the string keys represent the event names, and the values represent the handler for that event.</param>
 /// <param name="selector">A selector string to filter the descendants of the selected elements that trigger the event.</param>
 /// <param name="data">A custom data structure to be passed to the handler</param>
 /// <returns>The current jElement</returns>
 public jElement on(JsDictionary eventsMap, string selector, object data) {
     return null;
 }
示例#24
0
 /// <summary>
 /// Sets the specified name/value pairs as data on the matching set of elements.
 /// This extends any existing data on the element.
 /// </summary>
 /// <param name="data">The set of name/value pairs to set.</param>
 /// <returns>The current jElement.</returns>
 public jElement data(JsDictionary data) {
     return null;
 }
示例#25
0
 /// <summary>
 /// Removes an event handler which has been created by called On()
 /// </summary>
 /// <param name="eventsMap">A dictionary in which the string keys represent the event names, and the values represent the handler which was previously attached to that event</param>
 /// <param name="selector">A selector which should match the one originally passed to On()</param>
 /// <returns>The current jElement.</returns>
 public jElement off(JsDictionary eventsMap, string selector) {
     return null;
 }
示例#26
0
 /// <summary>
 /// Sets the specified CSS attributes to the set of matched elements.
 /// </summary>
 /// <param name="nameValueMap">The list of names and values of the CSS attributes to set.</param>
 /// <returns>The current jElement.</returns>
 public jElement css(JsDictionary nameValueMap) {
     return null;
 }
示例#27
0
 /// <summary>
 /// Attaches a handler for the specified event on the matched set of elements.
 /// </summary>
 /// <param name="eventName">The name of the event.</param>
 /// <param name="eventData">Any data that needs to be passed to the event handler.</param>
 /// <param name="eventHandler">The event handler to be invoked.</param>
 /// <returns>The current jElement</returns>
 public jElement bind(string eventName, JsDictionary eventData, jQueryEventHandler eventHandler) {
     return null;
 }
示例#28
0
 public static jQueryObject LostFocus(this jQueryObject q, JsDictionary eventData, jQueryEventHandler eventHandler) {
     return null;
 }
      public JsDictionary CreateDefinitionObject()
      {
         JsDictionary result = new JsDictionary();
         
         // maps name
         if(Name!=null) result["name"] = Name;

         // maps priority
         if(Priority!=null) result["priority"] = Priority;

         // maps restrict
         result["restrict"] = RestrictString();

         // maps template and templateUrl
              if(Template!=null) result["template"] = Template;
         else if(TemplateUrl!=null) result["templateUrl"] = TemplateUrl;

         // maps replace
         result["replace"] = Replace;

         // maps transclude
         result["transclude"] = Transclude;

         // maps scope
              if(ScopeMode == ScopeModes.Existing) result["scope"] = false;
         else if(ScopeMode == ScopeModes.New)      result["scope"] = true;
         else if(ScopeMode == ScopeModes.Isolate)
         {
            JsDictionary scope = new JsDictionary();
            foreach(ScopeBindings sb in ScopeAttributes)
            {
               scope[sb.AttributeName] = sb.ScopeBindingString();
            }
            result["scope"] = scope;
         }         

         // maps compile function
         
         // maps (shared) controller         
         if(SharedController != null)
         {
            var scontr = SharedController.BuildControllerFunction(ThisMode.This);
            result["controller"] = scontr;                            
         }                                                    

         // directive controller ('link' function) is managed during the registration process
                                                             
         // maps require
         if(Require!=null) result["require"] = Require;

         return result;
      }
示例#30
-1
            private object GetObjectValue(IXmlSchemaElementDefinition elementDefinition, XmlNode node)
            {
                XmlNodeList nilNodes = XPath.Evaluate(node, "./@i:nil", prefix => prefix == "i" ? "http://www.w3.org/2001/XMLSchema-instance" : null);
                if (nilNodes.Count == 1 && (nilNodes[0].Value == "true" || nilNodes[0].Value == "1"))
                {
                    return null;
                }

                IXmlSchemaSimpleTypeDefinition simpleTypeDefinition = elementDefinition.Type as IXmlSchemaSimpleTypeDefinition;
                if (simpleTypeDefinition != null)
                {
                    if (node.ChildNodes.Count != 1 || node.ChildNodes[0].NodeType != XmlNodeType.Text)
                    {
                        throw new InvalidOperationException("Expected text node as child for element " + elementDefinition.Name + ".");
                    }
                    string text = node.ChildNodes[0].Value;
                    switch (simpleTypeDefinition.Type)
                    {
                        case XmlBuiltInSimpleType.AnyType:
                        case XmlBuiltInSimpleType.AnyUri:
                        case XmlBuiltInSimpleType.Guid:
                        case XmlBuiltInSimpleType.QName:
                        case XmlBuiltInSimpleType.String:
                        case XmlBuiltInSimpleType.Enum:
                            return DecodeString(text);
                        case XmlBuiltInSimpleType.Base64Binary:
                            return StringUtility.FromBase64ToByteArray(text);
                        case XmlBuiltInSimpleType.Boolean:
                            return text == "true" || text == "1";
                        case XmlBuiltInSimpleType.Byte:
                            return FrameworkUtility.ByteTryParse(text);
                        case XmlBuiltInSimpleType.Char:
                            return (int)DecodeString(text)[0];
                        case XmlBuiltInSimpleType.Decimal:
                            return FrameworkUtility.DecimalTryParse(text);
                        case XmlBuiltInSimpleType.Double:
                            return FrameworkUtility.DoubleTryParse(text);
                        case XmlBuiltInSimpleType.Float:
                            return FrameworkUtility.FloatTryParse(text);
                        case XmlBuiltInSimpleType.Int:
                            return FrameworkUtility.IntTryParse(text);
                        case XmlBuiltInSimpleType.Long:
                            return FrameworkUtility.LongTryParse(text);
                        case XmlBuiltInSimpleType.Short:
                            return FrameworkUtility.ShortTryParse(text);
                        case XmlBuiltInSimpleType.UnsignedByte:
                            return FrameworkUtility.ByteTryParse(text);
                        case XmlBuiltInSimpleType.UnsignedInt:
                            return FrameworkUtility.IntTryParse(text);
                        case XmlBuiltInSimpleType.UnsignedLong:
                            return FrameworkUtility.LongTryParse(text);
                        case XmlBuiltInSimpleType.UnsignedShort:
                            return FrameworkUtility.ShortTryParse(text);
                        case XmlBuiltInSimpleType.DateTime:
                            string[] bits = text.Split(new Regex("[-T:+]", "g"));
                            int timeZoneStart;
                            int milliseconds;
                            if (bits.Length == 9)
                            {
                                timeZoneStart = 7;
                                milliseconds = FrameworkUtility.IntTryParse(bits[6]) ?? 0;
                            }
                            else
                            {
                                timeZoneStart = 6;
                                milliseconds = 0;
                            }
                            JsDate dateTime = new JsDate(int.Parse(bits[0]), int.Parse(bits[1]) - 1, int.Parse(bits[2]), int.Parse(bits[3]), int.Parse(bits[4]), int.Parse(bits[5]), milliseconds);
                            int offsetMinutes = int.Parse(bits[timeZoneStart])*60 + int.Parse(bits[timeZoneStart + 1]);
                            bool offsetIsNegative = new Regex("-\\d\\d:\\d\\d$").Test(text);
                            if (offsetIsNegative)
                            {
                                offsetMinutes *= -1;
                            }
                            dateTime.SetMinutes(dateTime.GetMinutes() - offsetMinutes - dateTime.GetTimezoneOffset());
                            return (DateTime)dateTime;
                        case XmlBuiltInSimpleType.Duration:
                            Regex regex = new Regex("([-+]?)P(([0-9]*)Y)?(([0-9]*)M)?(([0-9]*)D)?(T(([0-9]*)H)?(([0-9]*)M)?(([0-9.]*)S)?)?");
                            RegexMatch match = regex.Exec(text);
                            bool durationIsNegative = match[1] == "-";
                            int durationYears = match[3] == null ? 0 : FrameworkUtility.IntTryParse(match[3]) ?? 0;
                            int durationMonths = match[5] == null ? 0 : FrameworkUtility.IntTryParse(match[5]) ?? 0;
                            if (durationYears != 0 || durationMonths != 0)
                            {
                                throw new InvalidOperationException("Durations may not contain years or months.");
                            }
                            int durationDays = match[7] == null ? 0 : FrameworkUtility.IntTryParse(match[7]) ?? 0;
                            int durationHours = match[10] == null ? 0 : FrameworkUtility.IntTryParse(match[10]) ?? 0;
                            int durationMinutes = match[12] == null ? 0 : FrameworkUtility.IntTryParse(match[12]) ?? 0;
                            double durationFractionalSeconds = match[14] == null ? 0 : FrameworkUtility.DoubleTryParse(match[14]) ?? 0;
                            int durationSeconds = Math.Truncate(durationFractionalSeconds);
                            int durationMilliseconds = Math.Truncate(durationFractionalSeconds*1000)%1000;
                            if (durationIsNegative)
                            {
                                durationDays *= -1;
                                durationHours *= -1;
                                durationMinutes *= -1;
                                durationSeconds *= -1;
                                durationMilliseconds *= -1;
                            }
                            return new TimeSpan(durationDays, durationHours, durationMinutes, durationSeconds, durationMilliseconds);
                        default:
                            throw UnhandledEnumValueExceptionFactory.Create(simpleTypeDefinition.Type);
                    }
                }

                IXmlSchemaComplexTypeDefinition complexTypeDefinition = elementDefinition.Type as IXmlSchemaComplexTypeDefinition;
                if (complexTypeDefinition == null)
                {
                    throw new InvalidOperationException("Unknown element type.");
                }
                JsDictionary d = new JsDictionary();
                foreach (IXmlSchemaElementDefinition childElementDefinition in complexTypeDefinition.Elements)
                {
                    d[childElementDefinition.Name] = GetObjectRecursive(childElementDefinition, node);
                }
                return d;
            }