text: var should = require("should");
  var rp = require("../");
  var checkRefs = require("./checkRefs");
  
  describe("infer", function() {
  	it("should infer primitive operations", checkRefs(function() {
  		var x = rp.variable(123);
  		var y = rp.variable("string");
  		
  		x.plus(4)().should.be.eql(127);
  		y.plus(4)().should.be.eql("string4");
  		x.minus(4)().should.be.eql(119);
  		x.multipliedBy(2)().should.be.eql(123*2);
  		x.dividedBy(2)().should.be.eql(123/2);
  		var xy = x.plus(y)
  		xy().should.be.eql("123string");
  		x.dividedBy(2).minus(4).floored()().should.be.eql(57);
  		x.dividedBy(2).ceiled()().should.be.eql(62);
  		var test = rp.const(144).dividedBy(x).rounded().scope();
  		test().should.be.eql(1);
  		
  		x.set(5);
  		xy().should.be.eql("5string");
  		test().should.be.eql(29);
  		
  		y.set("test");
  		xy().should.be.eql("5test");
  		xy.isWritable().should.be.eql(false);
  	}));
  	
  	it("should calculate object keys", checkRefs(function() {
  		var x = rp.variable({a: 1, b: 2});
  		var y = x.keys();
  		y().should.be.eql(["a", "b"]);
  		x.set("c", 3);
  		y().should.be.eql(["a", "b", "c"]);
  		x.set("a", undefined);
  		y().should.be.eql(["b", "c"]);
  		x.set({x: 4, y: 5});
  		y().should.be.eql(["x", "y"]);
  		x.set(5);
  		y().should.be.eql([]);
  		x.set({});
  		y().should.be.eql([]);
  	}));
  	
  	it("should flatten an array", checkRefs(function() {
  		var x = rp.variable([[1, 2, 3], [4], [5, 6], [], [7]]);
  		var y = x.flatten();
  		y().should.be.eql([1,2,3,4,5,6,7]);
  		x.pop();
  		y().should.be.eql([1,2,3,4,5,6]);
  		x.push([7, 8, 9]);
  		y().should.be.eql([1,2,3,4,5,6,7,8,9]);
  		x.splice(2, 1, ["five"], ["six"]);
  		y().should.be.eql([1,2,3,4,"five","six",7,8,9]);
  		x(0).push(3.5);
  		y().should.be.eql([1,2,3,3.5,4,"five","six",7,8,9]);
  		x(1).set(["four"]);
  		y().should.be.eql([1,2,3,3.5,"four","five","six",7,8,9]);
  	}));
  	
  	it("should double flatten an array", checkRefs(function() {
  		var x = rp.variable([[[1], [2, 3]], [[], [], []], [[4]]]);
  		var y = x.flatten();
  		var z = y.flatten();
  		var zz = z.map(String);
  		zz().should.be.eql(["1","2","3","4"]);
  		x(0).push([3.5]);
  		zz().should.be.eql(["1","2","3","3.5","4"]);
  		x(1, 1).push(3.75);
  		zz().should.be.eql(["1","2","3","3.5","3.75","4"]);
  	}));
  	
  	it("should flatten a complex delegated array", checkRefs(function() {
  		var x = rp.variable({
  			a: {
  				x: { value: 1 },
  				y: { value: 2 }
  			},
  			c: {},
  			b: {
  				z: { value: 3 }
  			}
  		});
  		var y = rp.delegated(function() {
  			return x.keys().map(function(xKey) {
  				var xObj = x(xKey);
  				return xObj.keys().map(function(xxKey) {
  					return xObj(xxKey);
  				});
  				// an array of RPs
  			})
  			// an array of RP (array of RPs)
  			.delegated()
  			// an array of arrays of RPs
  			.flatten()
  			// an array of RPs
  			.delegated();
  			// an array of objects
  		});
  		
  		y().should.be.eql([
  			{ value: 1 },
  			{ value: 2 },
  			{ value: 3 }
  		]);
  		y(1);
  		var two = y(1, "value").computed(String);
  		two().should.be.eql("2");
  		var twoChanged = false;
  		two.onChanged(function() {
  			twoChanged = true;
  		});
  		x("a", "y", "value").set("two");
  		twoChanged.should.be.eql(true);
  		twoChanged = false;
  		two().should.be.eql("two");
  		y().should.be.eql([
  			{ value: 1 },
  			{ value: "two" },
  			{ value: 3 }
  		]);
  		x("a", "y").set({ value: "other" });
  		twoChanged.should.be.eql(true);
  		twoChanged = false;
  		two().should.be.eql("other");
  		y().should.be.eql([
  			{ value: 1 },
  			{ value: "other" },
  			{ value: 3 }
  		]);
  	}));
  });