<commit_before>var tape = require('tape');
var State = require('../ampersand-state');
var AmpersandRegistry = require('ampersand-registry');
var definition, Foo, registry;


// wrap test so we always run reset first
var test = function () {
    reset();
    tape.apply(tape, arguments);
};

function reset() {
    registry = new AmpersandRegistry();

    definition = {
        type: 'foo',
        props: {
            id: 'number',
            firstName: ['string', true, 'defaults'],
            lastName: ['string', true],
            thing: {
                type: 'string',
                required: true,
                default: 'hi'
            },
            num: ['number', true],
            today: ['date'],
            hash: ['object'],
            list: ['array'],
            myBool: ['boolean', true, false],
            someNumber: {type: 'number', allowNull: true},
            good: {
                type: 'string',
                test: function (newVal) {
                    if (newVal !== 'good') {
                        return "Value not good";
                    }
                }
            }
        },
        session: {
            active: ['boolean', true, true]
        },
        derived: {
            name: {
                deps: ['firstName', 'lastName'],
                fn: function () {
                    return this.firstName + ' ' + this.lastName;
                }
            },
            initials: {
                deps: ['firstName', 'lastName'],
                cache: false,
                fn: function () {
                    // This currently breaks without both deps being set
                    if (this.firstName && this.lastName) {
                        return (this.firstName.charAt(0) + this.lastName.charAt(0)).toUpperCase();
                    }
                    return '';
                }
            },
            isCrazy: {
                deps: ['crazyPerson'],
                fn: function () {
                    return !!this.crazyPerson;
                }
            }
        },
        // add a reference to the registry
        registry: registry
    };

    Foo = State.extend(definition);
}


test('should get the derived value', function (t) {
    var foo = new Foo({
        firstName: 'jim',
        lastName: 'tom'
    });
    foo.firstName = 'jim';
    foo.lastName = 'tom';

    t.strictEqual(foo.name, '<NAME>');
    t.strictEqual(foo.initials, 'JT');
    t.end();
});

test('should be sealable', function (t) {
    definition.seal = true;
    var Bar = State.extend(definition);
    var bar = new Bar();
    t.throws(function () {
        "use strict";
        bar.someProperty = 'new';
    }, TypeError, 'Throws exception in strict mode.');
    bar.someOtherProperty = 'something';
    t.ok(!bar.someOtherProperty, 'ignores properties otherwise');
    t.end();
});

test('should have default values for properties', function (t) {
    var foo = new Foo({
        firstName: 'jim',
        lastName: 'tom'
    });
    t.strictEqual(foo.myBool, false);
    t.end();
});

test('should throw an error setting a derived prop', function (t) {
    var foo = new Foo();
    try { foo.name = 'bob'; }
    catch (err) { t.ok(err instanceof TypeError); }
    t.end();
});

test('Error when setting derived property should be helpful', function (t) {
    var foo = new Foo();
    try { foo.name = 'bob'; }
    catch (err) {
        t.equal(err.message, "\"name\" is a derived property, it can't be set directly.");
    }<commit_msg>detect and work around strictmode missing in IE9<commit_after>var tape = require('tape');
var State = require('../ampersand-state');
var AmpersandRegistry = require('ampersand-registry');
var definition, Foo, registry;


// wrap test so we always run reset first
var test = function () {
    reset();
    tape.apply(tape, arguments);
};

function reset() {
    registry = new AmpersandRegistry();

    definition = {
        type: 'foo',
        props: {
            id: 'number',
            firstName: ['string', true, 'defaults'],
            lastName: ['string', true],
            thing: {
                type: 'string',
                required: true,
                default: 'hi'
            },
            num: ['number', true],
            today: ['date'],
            hash: ['object'],
            list: ['array'],
            myBool: ['boolean', true, false],
            someNumber: {type: 'number', allowNull: true},
            good: {
                type: 'string',
                test: function (newVal) {
                    if (newVal !== 'good') {
                        return "Value not good";
                    }
                }
            }
        },
        session: {
            active: ['boolean', true, true]
        },
        derived: {
            name: {
                deps: ['firstName', 'lastName'],
                fn: function () {
                    return this.firstName + ' ' + this.lastName;
                }
            },
            initials: {
                deps: ['firstName', 'lastName'],
                cache: false,
                fn: function () {
                    // This currently breaks without both deps being set
                    if (this.firstName && this.lastName) {
                        return (this.firstName.charAt(0) + this.lastName.charAt(0)).toUpperCase();
                    }
                    return '';
                }
            },
            isCrazy: {
                deps: ['crazyPerson'],
                fn: function () {
                    return !!this.crazyPerson;
                }
            }
        },
        // add a reference to the registry
        registry: registry
    };

    Foo = State.extend(definition);
}


test('should get the derived value', function (t) {
    var foo = new Foo({
        firstName: 'jim',
        lastName: 'tom'
    });
    foo.firstName = 'jim';
    foo.lastName = 'tom';

    t.strictEqual(foo.name, '<NAME>');
    t.strictEqual(foo.initials, 'JT');
    t.end();
});

test('should be sealable', function (t) {
    definition.seal = true;
    var Bar = State.extend(definition);
    var bar = new Bar();
    t.throws(function () {
        "use strict";
        // detect if strict mode worked
        var isStrict = (function () { return !this; })();
        bar.someProperty = 'new';
        // throw type error to be able to test in browsers
        // that don't support strict
        if (!isStrict) throw TypeError;
    }, TypeError, 'Throws exception in strict mode.');
    bar.someOtherProperty = 'something';
    t.ok(!bar.someOtherProperty, 'ignores properties otherwise');
    t.end();
});

test('should have default values for properties', function (t) {
    var foo = new Foo({
        firstName: 'jim',
        lastName: 'tom'
    });
    t.strictEqual(foo.myBool, false);
    t.end();
});

test('should throw an error setting a derived prop', function (t) {
    var foo = new Foo();
    try { foo.name = 'bob'; }
    catch (err) { t.ok(err instanceof TypeError); }
    t.end();
});

test('Error when setting derived property should be helpful', function (t) {
    var foo = new Foo();
    try { foo.name = 'bob'; }
    catch (err) {
        t.equal(err.message, "\"name\" is a derived property, it can't be set directly.");
    }
{'fraction_non_alphanumeric': 0.139188635432318, 'fraction_numerical': 0.0006829668078131403, 'mean_word_length': 1.5646234676007005, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4572936', 'n_tokens_mistral': 2068, 'n_tokens_neox': 1988, 'n_words': 567}