コード例 #1
0
  test('JSCheck Custom Specifier for SSN', function() {
    /**
     * Produces a valid social security string (with dashes)
     * @param param1 Area Number -> JSC.integer(100, 999)
     * @param param2 Group Number -> JSC.integer(10, 99)
     * @param param3 Serial Number -> JSC.integer(1000,9999)
     * @returns {Function} Specifier function
     */
    JSC.SSN = function(param1, param2, param3) {
      return function generator() {
        const part1 = typeof param1 === 'function' ? param1() : param1
        const part2 = typeof param2 === 'function' ? param2() : param2
        const part3 = typeof param3 === 'function' ? param3() : param3
        return [part1, part2, part3].join('-')
      }
    }
    // Functions to test
    const validLength = (len, str) => str.length === len

    const find = R.curry((db, id) => db.find(id))

    const checkLengthSsn = ssn => {
      return Either.of(ssn).filter(R.partial(validLength, [9]))
    }

    JSC.clear()

    JSC.on_report(report => console.log('Report' + str))

    JSC.on_pass(object => assert.ok(object.pass))

    JSC.on_fail(object =>
      expect(
        object.pass || object.args.length === 9,
        'Test failed for: ' + object.args
      ).toEqual(true)
    )

    JSC.test(
      'Check Length SSN',
      function(verdict, ssn) {
        return verdict(checkLengthSsn(ssn))
      },
      [
        JSC.SSN(
          JSC.integer(100, 999),
          JSC.integer(10, 99),
          JSC.integer(1000, 9999)
        ),
      ],
      function(ssn) {
        return 'Testing Custom SSN: ' + ssn
      }
    )

    expect(0)
  })
コード例 #2
0
 it('check nested indexed sequences', function() {
   JSC.test('add when value added in nested sequence', function(veredict, obj, newInt) {
     var map1 = Immutable.fromJS(obj);
     var map2 = Immutable.fromJS(obj).updateIn(['b', 'c'], function(list) {
       return list.push(newInt);
     });
     var result = diff(map1, map2);
     var expected = Immutable.fromJS([{
       op: 'add',
       path: '/b/c/5',
       value: newInt
     }]);
     return veredict(Immutable.is(result, expected));
   }, [JSC.object({
     a: JSC.integer(),
     b: JSC.object({c: JSC.array(5, JSC.integer())})
   }), JSC.integer()]);
   JSC.test('remove when value removed in nested sequence', function(veredict, obj, removeIdx) {
     var map1 = Immutable.fromJS(obj);
     var map2 = Immutable.fromJS(obj).updateIn(['b', 'c'], function(list) {
       return list.splice(removeIdx, 1);
     });
     var result = diff(map1, map2);
     var expected = Immutable.fromJS([{
       op: 'remove',
       path: '/b/c/' + removeIdx
     }]);
     return veredict(Immutable.is(result, expected));
   }, [JSC.object({
     a: JSC.integer(),
     b: JSC.object({c: JSC.array(10, JSC.integer())})
   }), JSC.integer(0, 9)]);
   JSC.test('replace when values are replaced in nested sequence', function(veredict, obj, replaceIdx, newValue) {
     var map1 = Immutable.fromJS(obj);
     var map2 = Immutable.fromJS(obj).updateIn(['b', 'c'], function(list) {
       return list.set(replaceIdx, newValue);
     });
     var result = diff(map1, map2);
     var expected = Immutable.fromJS([{
       op: 'replace',
       path: '/b/c/' + replaceIdx,
       value: newValue
     }]);
     return veredict(Immutable.is(result, expected));
   }, [JSC.object({
     a: JSC.integer(),
     b: JSC.object({c: JSC.array(10, JSC.integer())})
   }), JSC.integer(0, 9), JSC.integer()]);
 });
コード例 #3
0
// Anything but an object, array, or undefined.
function invalidMergeArgumentSpecifier() {
  return JSC.one_of([
    (function() { return function() {}; }),
    JSC.integer(), JSC.number(), JSC.string(),
    true, Infinity, -Infinity
  ]);
}
コード例 #4
0
  test('Run JSCHeck', function() {
    // Functions to test
    const fork = (join, func1, func2) => val => join(func1(val), func2(val))

    const toLetterGrade = grade => {
      if (grade >= 90) return 'A'
      if (grade >= 80) return 'B'
      if (grade >= 70) return 'C'
      if (grade >= 60) return 'D'
      return 'F'
    }

    const computeAverageGrade = R.compose(
      toLetterGrade,
      fork(R.divide, R.sum, R.length)
    )

    JSC.clear()
    JSC.on_report(str => console.log(str))
    JSC.test(
      'Compute Average Grade',
      function(verdict, grades, grade) {
        return verdict(computeAverageGrade(grades) === grade)
      },
      [JSC.array(JSC.integer(20), JSC.number(90, 100)), 'A'],
      function(grades, grade) {
        return 'Testing for an ' + grade + ' on grades: ' + grades
      }
    )
    expect(0)
  })
コード例 #5
0
      check(100, [ JSC.array([TestUtils.TraversableObjectSpecifier]) ], function(array) {
        var immutable = Immutable(array);
        var mutable = array.slice();

        var idx = JSC.integer(0, array.length-1);
        var key = JSC.one_of(_.keys(immutable[idx]))();
        var value;
        do {
          value = JSC.any()();
        } while (TestUtils.isDeepEqual(value, immutable[idx][key]));

        TestUtils.assertJsonEqual(immutable, mutable);

        var resultImmutable = Immutable.setIn(immutable, [idx, key], value, {deep: true});
        var resultMutable = mutable.slice();
        resultMutable[idx][key] = value;
        
        TestUtils.assertJsonEqual(
          resultImmutable,
          resultMutable
        );
        assert.notEqual(
          immutable,
          resultImmutable
        );
        assert.equal(
          Immutable.setIn(resultImmutable, [idx, key], value, {deep: true}),
          resultImmutable
        );
      });
コード例 #6
0
      check(100, [ JSC.array([TestUtils.TraversableObjectSpecifier]) ], function(array) {
        var immutable = Immutable(array);
        var mutable = array.slice();
        var index = JSC.integer(0, array.length);
        var value;

        var newValue;
        do {
          value = JSC.any()();
        } while (TestUtils.isDeepEqual(value, array[index]));

        var resultImmutable = Immutable.set(immutable, index, newValue, {deep: true});
        var resultMutable = mutable.slice();
        resultMutable[index] = newValue;

        TestUtils.assertJsonEqual(
          resultImmutable,
          resultMutable
        );
        assert.notEqual(
          immutable,
          resultImmutable
        );
        assert.equal(
          Immutable.set(resultImmutable, index, newValue, {deep: true}),
          resultImmutable
        );
      });
コード例 #7
0
    it("cannot have its elements directly mutated", function() {
      checkImmutableMutable(function(immutable, mutable, randomIndex, randomData) {
        immutable[randomIndex] = randomData;

        assert.typeOf(randomIndex, "number");
        assert.strictEqual(immutable.length, mutable.length);
        assert.deepEqual(immutable[randomIndex], mutable[randomIndex]);
      }, [JSC.integer(), JSC.any()]);
    });
コード例 #8
0
      check(100, [ JSC.array([TestUtils.TraversableObjectSpecifier]) ], function(array) {
        var immutable = Immutable(array);
        var idx = JSC.integer(0, array.length-1);
        var key = JSC.one_of(_.keys(immutable[idx]))();
        var value = immutable[idx][key];

        TestUtils.assertJsonEqual(
          Immutable.getIn(immutable, [idx, key]),
          value
        );
      });
コード例 #9
0
    var obj = _.object(_.map(JSC.array()(), function() {
      var key   = JSC.string()();
      var value = JSC.one_of([JSC.array(), JSC.object(),
        JSC.falsy(), JSC.integer(), JSC.number(), JSC.string(),
        true, Infinity, -Infinity])();

      if (typeof value === "object") {
        return [key, withoutItengerKeys(value)];
      }

      return [key, value];
    }));
コード例 #10
0
      check(100, [ JSC.array([TestUtils.TraversableObjectSpecifier, JSC.any()]) ], function(array) {
        var immutable = Immutable(array);
        var mutable = array.slice();
        var index = JSC.integer(0, array.length);
        var newValue = JSC.any();

        var resultImmutable = Immutable.set(immutable, index, newValue);
        var resultMutable = mutable.slice();
        resultMutable[index] = newValue;

        TestUtils.assertJsonEqual(resultImmutable, resultMutable);
      });
コード例 #11
0
 it('check properties', function() {
   JSC.test('returns [] when equal', function(veredict, obj) {
     var map1 = Immutable.fromJS(obj);
     var map2 = Immutable.fromJS(obj);
     var result = diff(map1, map2);
     return veredict(result.count() === 0);
   }, [JSC.object(5)]);
   JSC.test('returns add op when missing attribute', function(veredict, obj, obj2) {
     var map1 = Immutable.fromJS(obj);
     var map2 = Immutable.fromJS(obj).set('key2', obj2.key2);
     var result = diff(map1, map2);
     var expected = Immutable.fromJS([{
       op: 'add',
       path: '/key2',
       value: obj2.key2
     }]);
     return veredict(Immutable.is(result, expected));
   }, [JSC.object({key: JSC.integer()}), JSC.object({key2: JSC.integer()})]);
   JSC.test('returns replace op when same attribute with different values', function(veredict, obj, newValue) {
     var map1 = Immutable.fromJS(obj);
     var map2 = Immutable.fromJS(obj).set('key', newValue);
     var result = diff(map1, map2);
     var expected = Immutable.fromJS([{
       op: 'replace',
       path: '/key',
       value: newValue
     }]);
     return veredict(Immutable.is(result, expected));
   }, [JSC.object({key: JSC.integer(1, 100)}), JSC.integer(101, 200)]);
   JSC.test('returns remove op when attribute is missing', function(veredict, obj) {
     var map1 = Immutable.fromJS(obj);
     var map2 = Immutable.Map();
     var result = diff(map1, map2);
     var expected = Immutable.fromJS([{
       op: 'remove',
       path: '/key'
     }]);
     return veredict(Immutable.is(result, expected));
   }, [JSC.object({key: JSC.integer()})]);
 });
コード例 #12
0
      check(100, [ JSC.array([TestUtils.TraversableObjectSpecifier]) ], function(array) {
        var immutable = Immutable(array);
        var mutable = array.slice();
        var value = JSC.any()();

        var idx = JSC.integer(0, array.length-1);
        var key = JSC.one_of(_.keys(immutable[idx]))();

        var util = require('util');
        function printArr(arr) {
          return '[\n\t>'+_.map(arr, util.inspect).join('\n\t>')+'\n]';
        }

        TestUtils.assertJsonEqual(immutable, mutable);
        var resultMutable = mutable.slice();
        resultMutable[idx][key] = value;

        TestUtils.assertJsonEqual(
          Immutable.setIn(immutable, [idx, key], value),
          resultMutable
        );
      });
コード例 #13
0
 it("supports accessing elements by index via []", function() {
   checkImmutableMutable(function(immutable, mutable, index) {
     assert.typeOf(index, "number");
     assert.deepEqual(immutable[index], mutable[index]);
   }, [JSC.integer()]);
 });
コード例 #14
0
module.exports = function(config) {
  var Immutable = config.implementation;
  var TestUtils = getTestUtils(Immutable);

  var checkImmutableMutable = TestUtils.checkImmutableMutable(100, [JSC.array([TestUtils.ComplexObjectSpecifier()])]);

  describe("ImmutableArray", function() {
    describe("which is compatible with vanilla mutable arrays", function() {
      it("is an instance of Array", function() {
        checkImmutableMutable(function(immutable, mutable) {
          assert.instanceOf(immutable, Array);
        });
      });

      it("has the same length as its mutable equivalent", function() {
        checkImmutableMutable(function(immutable, mutable) {
          assert.strictEqual(immutable.length, mutable.length);
        });
      });

      it("supports accessing elements by index via []", function() {
        checkImmutableMutable(function(immutable, mutable, index) {
          assert.typeOf(index, "number");
          TestUtils.assertJsonEqual(immutable[index], mutable[index]);
        }, [JSC.integer()]);
      });

      it("works with for loops", function() {
        checkImmutableMutable(function(immutable, mutable) {
          for (var index=0; index < immutable.length; index++) {
            TestUtils.assertJsonEqual(immutable[index], mutable[index]);
          }
        });
      });

      it("works with for..in loops", function() {
        checkImmutableMutable(function(immutable, mutable) {
          for (var index in immutable) {
            TestUtils.assertJsonEqual(immutable[index], mutable[index]);
          }
        });
      });

      it("supports concat", function() {
        checkImmutableMutable(function(immutable, mutable, otherArray) {
          TestUtils.assertJsonEqual(immutable.concat(otherArray), mutable.concat(otherArray));
        }, [JSC.array()]);
      });

      it("supports being an argument to a normal immutable's concat", function() {
        checkImmutableMutable(function(immutable, mutable, otherArray) {
          TestUtils.assertJsonEqual(otherArray.concat(immutable), otherArray.concat(mutable));
        }, [JSC.array()]);
      });

      it("can be concatted to itself", function() {
        checkImmutableMutable(function(immutable, mutable) {
          TestUtils.assertJsonEqual(immutable.concat(immutable), mutable.concat(mutable));
        });
      });

      it("has a toString() method that works like a regular immutable's toString()", function() {
        checkImmutableMutable(function(immutable, mutable) {
          assert.strictEqual(immutable.toString(), mutable.toString());
        });
      });

      it("supports being passed to JSON.stringify", function() {
        checkImmutableMutable(function(immutable, mutable) {
          TestUtils.assertJsonEqual(JSON.stringify(immutable), JSON.stringify(mutable));
        });
      });

      if (config.id === "dev") {
        it("is frozen", function() {
          checkImmutableMutable(function(immutable, mutable) {
            assert.isTrue(Object.isFrozen(immutable));
          });
        });
      }

      if (config.id === "prod") {
        it("is not frozen", function() {
          checkImmutableMutable(function(immutable, mutable) {
            assert.isFalse(Object.isFrozen(immutable));
          });
        });
      }

      it("is tagged as immutable", function() {
        checkImmutableMutable(function(immutable, mutable) {
          TestUtils.assertIsDeeplyImmutable(immutable);
        })
      });

      if (config.id === "dev") {
        it("cannot have its elements directly mutated", function () {
          checkImmutableMutable(function (immutable, mutable, randomIndex, randomData) {
            immutable[randomIndex] = randomData;

            assert.typeOf(randomIndex, "number");
            assert.strictEqual(immutable.length, mutable.length);
            TestUtils.assertJsonEqual(immutable[randomIndex], mutable[randomIndex]);
          }, [JSC.integer(), JSC.any()]);
        });
      }

      if (config.id === "prod") {
        it("can have its elements directly mutated", function () {
          var immutableArr = Immutable([1, 2, 3]);
          immutableArr[0] = 4;
          assert.equal(immutableArr[0], 4);

          immutableArr.sort();
          TestUtils.assertJsonEqual(immutableArr, [2, 3, 4]);
        });
      }

      it("makes nested content immutable as well", function() {
        checkImmutableMutable(function(immutable, mutable, innerArray, obj) {
          mutable.push(innerArray); // Make a nested immutable
          mutable.push(obj); // Get an object in there too

          immutable = Immutable(mutable);

          assert.strictEqual(immutable.length, mutable.length);

          for (var index in mutable) {
            TestUtils.assertIsDeeplyImmutable(immutable[index]);
          }

          TestUtils.assertIsDeeplyImmutable(immutable);
        });
      });

      // TODO this never fails under Node, even after removing Immutable.Array's
      // call to toImmutable(). Need to verify that it can fail in browsers.
      it("reuses existing immutables during construction", function() {
        checkImmutableMutable(function(immutable, mutable, innerArray, obj) {
          mutable.push(innerArray); // Make a nested immutable
          mutable.push(obj); // Get an object in there too

          immutable = Immutable(mutable);

          var copiedArray = Immutable(immutable);

          assert.strictEqual(copiedArray.length, immutable.length);

          for (var index in copiedArray) {
            TestUtils.assertJsonEqual(immutable[index], copiedArray[index]);
          }
        }, [JSC.array(), JSC.object()]);
      });
    });
  });

  // Add a "returns immutable" claim for each non-mutating method on Array.
  nonMutatingArrayMethods = {
    map:         [JSC.literal(identityFunction)],
    filter:      [JSC.literal(identityFunction)],
    reduce:      [JSC.literal(identityFunction), JSC.any()],
    reduceRight: [JSC.literal(identityFunction), JSC.any()],
    concat:      [JSC.array()],
    slice:       [JSC.integer(), JSC.integer()]
  }

  _.each(nonMutatingArrayMethods, function(specifiers, methodName) {
    it("returns only immutables when you call its " +
        methodName + "() method", function() {
      checkImmutableMutable(function(immutable, mutable) {
        var methodArgs = specifiers.map(function(generator) { return generator() });
        TestUtils.assertImmutable(methodName, immutable, mutable, methodArgs);
      });
    });
  });

  [ // Add a "reports banned" claim for each mutating method on Array.
    "setPrototypeOf", "push", "pop", "sort", "splice", "shift", "unshift", "reverse"
  ].forEach(function(methodName) {
    var description = "it throws an ImmutableError when you try to call its " +
      methodName + "() method";

    checkImmutableMutable(function(immutable, mutable, innerArray, obj) {
      assert.throw(function() {
        array[methodName].apply(array, methodArgs);
      });
    }, Immutable.ImmutableError);
  });
};
コード例 #15
0
  it('check properties', function() {
    JSC.test(
      'returns [] when equal',
      function(veredict, int1){
        var result = diff(int1, int1);
        var expected = Immutable.fromJS([]);

        return veredict(Immutable.is(result, expected));
      },
      [
        JSC.integer()
      ]
    );

    JSC.test(
      'replaces numbers',
      function(veredict, int1, int2){
        var result = diff(int1, int2);
        var expected = Immutable.fromJS([
          {op: 'replace', path: '/', value: int2}
        ]);

        return veredict(Immutable.is(result, expected));
      },
      [
        JSC.integer(),
        JSC.integer()
      ]
    );

    JSC.test(
      'replaces strings',
      function(veredict, str1, str2){
        var result = diff(str1, str2);
        var expected = Immutable.fromJS([
          {op: 'replace', path: '/', value: str2}
        ]);

        return veredict(Immutable.is(result, expected));
      },
      [
        JSC.string(),
        JSC.string()
      ]
    );

    JSC.test(
      'replaces arrays',
      function(veredict, array1, array2){
        var result = diff(array1, array2);
        var expected = Immutable.fromJS([
          {op: 'replace', path: '/', value: array2}
        ]);

        return veredict(Immutable.is(result, expected));
      },
      [
        JSC.array(5),
        JSC.array(5)
      ]
    );

    JSC.test(
      'replaces objects',
      function(veredict, object1, object2){
        var result = diff(object1, object2);
        var expected = Immutable.fromJS([
          {op: 'replace', path: '/', value: object2}
        ]);

        return veredict(Immutable.is(result, expected));
      },
      [
        JSC.object(5),
        JSC.object(5)
      ]
    );
  });
コード例 #16
0
 it('check nested structures', function() {
   JSC.test('returns add op when missing attribute in nested structure', function(veredict, obj, obj2) {
     var map1 = Immutable.fromJS(obj);
     var map2 = Immutable.fromJS(obj).setIn(['b', 'd'], obj2.d);
     var result = diff(map1, map2);
     var expected = Immutable.fromJS([{
       op: 'add',
       path: '/b/d',
       value: obj2.d
     }]);
     return veredict(Immutable.is(result, expected));
   }, [JSC.object({
     a: JSC.integer(),
     b: JSC.object({c: JSC.integer()})
   }), JSC.object({d: JSC.integer()})]);
   JSC.test('returns replace op when different value in nested structure', function(veredict, obj, obj2) {
     var map1 = Immutable.fromJS(obj);
     var map2 = Immutable.fromJS(obj).setIn(['b', 'c'], obj2.c);
     var result = diff(map1, map2);
     var expected = Immutable.fromJS([{
       op: 'replace',
       path: '/b/c',
       value: obj2.c
     }]);
     return veredict(Immutable.is(result, expected));
   }, [JSC.object({
     a: JSC.integer(),
     b: JSC.object({c: JSC.integer(1, 100)})
   }), JSC.object({c: JSC.integer(101, 200)})]);
   JSC.test('returns remove op when attribute removed in nested structure', function(veredict, obj, obj2) {
     var map1 = Immutable.fromJS(obj).setIn(['b', 'd'], obj2.d);
     var map2 = Immutable.fromJS(obj);
     var result = diff(map1, map2);
     var expected = Immutable.fromJS([{
       op: 'remove',
       path: '/b/d'
     }]);
     return veredict(Immutable.is(result, expected));
   }, [JSC.object({
     a: JSC.integer(),
     b: JSC.object({c: JSC.integer()})
   }), JSC.object({d: JSC.integer()})]);
   JSC.test('no replace in equal nested structure', function(veredict, obj, obj2) {
     var map1 = Immutable.fromJS(obj);
     var map2 = Immutable.fromJS(obj).set('a', obj2.a);
     var result = diff(map1, map2);
     var expected = Immutable.fromJS([{
       op: 'replace',
       path: '/a',
       value: obj2.a
     }]);
     return veredict(Immutable.is(result, expected));
   }, [JSC.object({
     a: JSC.integer(),
     b: JSC.object({c: JSC.integer()})
   }), JSC.object({a: JSC.integer()})]);
   JSC.test('add/remove when different nested structure', function(veredict, obj, obj2) {
     var map1 = Immutable.fromJS(obj);
     var map2 = Immutable.fromJS(obj).set('b', Immutable.fromJS(obj2));
     var result = diff(map1, map2);
     var expected = Immutable.fromJS([{
       op: 'remove',
       path: '/b/c'
     }, {
       op: 'add',
       path: '/b/e',
       value: obj2.e
     }]);
     return veredict(Immutable.is(result, expected));
   }, [JSC.object({
     a: JSC.integer(),
     b: JSC.object({c: JSC.integer()})
   }), JSC.object({e: JSC.integer()})]);
 });