<commit_before>/*
 * Copyright (c) 2011-2013, Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */

/*jshint node:true */
/*global describe,it */
'use strict';

var chai,
    expect,
    IntlMessageFormat;

// This oddity is so that this file can be used for both client-side and
// server-side testing.  (On the client we've already loaded chai and
// IntlMessageFormat.)
if ('function' === typeof require) {
    chai = require('chai');
    IntlMessageFormat = require('../build/index.en.min.js');
    require('../locale-data/ar.js');
    require('../locale-data/pl.js');
}
expect = chai.expect;

describe('message resolvedOptions', function () {

    it('empty options', function () {
        var msg, o, p, pCount = 0;

        msg = new IntlMessageFormat('My name is ${name}');

        o = msg.resolvedOptions();

        for (p in o) {
            if (o.hasOwnProperty(p)) {
                pCount++;
            }
        }

        expect(pCount).to.equal(0);
    });
});

describe('message creation', function () {

    it('simple string formatting', function () {
        var msg, m;
        msg = new IntlMessageFormat('My name is ${first} {last}.');
        m = msg.format({
            first: 'Anthony',
            last: 'Pipkin'
        });
        expect(m).to.equal('My name is Anthony Pipkin.');
    });

    it('simple object formatting', function () {
        var msg, m;

        msg = new IntlMessageFormat(['I have ', 2, ' cars.']);

        m = msg.format();

        expect(m).to.equal('I have 2 cars.');

    });

    it('simple object with post processing tokens', function () {
        var msg, m;

        msg = new IntlMessageFormat(['${', 'company', '}', ' {', 'verb' ,'}.']);

        m = msg.format({
            company: 'Yahoo',
            verb: 'rocks'
        });

        expect(m).to.equal('Yahoo rocks.');

    });

    it ('complex object formatter', function () {
        var msg, m;
        msg = new IntlMessageFormat(['Some text before ', {
            type: 'plural',
            valueName: 'numPeople',
            options: {
                one: 'one',

                few: 'few',

                other: 'Some messages for the default'
            }
        }, ' and text after']);

        m = msg.format({
            numPeople: 20
        });

        expect(m).to.equal("Some text before Some messages for the default and text after");
    });

    it ('complex object formatter with invalid valueName', function () {
        var msg, m;
        msg = new IntlMessageFormat(['Some text before ', {
            type: 'plural',
            valueName: 'numPeople',
            options: {
                one: 'one',

                few: 'few',

                other: 'Some messages for the default'
            }
        }, ' and text after']);

        try {
            m = msg.format({
                jumper: 20
            });
        } catch (e) {
            var err = 'The valueName `numPeople` was not found.';
            expect(e).to.equal(err);
        }
    });

    it ('complex object formatter with offset', function () {
        var msg, m;
        msg = new IntlMessageFormat(['Some text before ', {
            type: 'plural',
            valueName: 'numPeople',
            offset: 1,
            options: {
                one: 'Some message ${ph} with ${#} value',

                few: ['Optional prefix text for |few| ', {
                    type: 'select',
                    valueName: 'gender',
                    options: {
                        male: 'Text for male option with \' single quotes',
                        female: 'Text for female option with {}',
                        other: 'Text for default'
                    }
                }, ' optional postfix text'],

                other: 'Some messages for the default'

            }
        }, ' and text after'],
            'pl'    // this has the "few" rule that we need
        );
        m = msg.format({
            numPeople: 1,   // offset will move this to "2" so that the "few" group is used
            ph: 'whatever',
            gender: 'male'
        });
        expect(m).to.equal("Some text before Optional prefix text for |few| Text for male option with ' single quotes optional postfix text and text after");
    });

    it('Simple string formatter using a custom formatter for a token', function () {
        var msg, m;
        msg = new IntlMessageFormat('Test formatter d: ${num:d}', null, {
            d: function (val, locale) {
                return +val;
            }
        });
        m = msg.format({
            num: '010'
        });
        expect(m).to.equal('Test formatter d: 10');
    });

    it('Simple string formatter using an inline formatter for a token', function () {
        var msg, m;
        msg = new IntlMessageFormat([{
            valueName: 'str',
            formatter: function (val, locale) {
                return val.toString().split('').reverse().join('');
            }
        }]);
        m = msg.format({
            str: 'aardvark'
        });
        expect(m).to.equal('kravdraa');
    });

    it('Simple string formatter using a nonexistent formatter for a token', function () {
        var msg, m;
        msg = new IntlMessageFormat('Test formatter foo: ${num:foo}', null, {
            d: function (val, locale) {
                return +val;
            }
        });
        m = msg.format({
            num: '010'
        });
        expect(m).to.equal('Test formatter foo: 010');
    });

    it('Custom formatters with hidden inheritance', function () {
        var msg, m,
            Formatters = function () {
                this.d = function (val, locale) {
                    return val + '030';
                };
            },
            CustomFormatters = function () {
                this.f = function (val, locale) {
                    return val + '080';
                };
            };

        CustomFormatters.prototype = Formatters;
        CustomFormatters.prototype.constructor = CustomFormatters;

        msg = new IntlMessageFormat('d: ${num:d} / f: ${num:f}', null, new CustomFormatters());

        m = msg.format({
            num: 0
        });

        expect(m).to.equal('d: 0 / f: 0080');
    });

    it('broken pattern', function () {
       var msg, m;

        msg = new IntlMessageFormat('${name} ${formula}');

        msg.pattern = '${name} ${formula}';

        m = msg.format({
            name: 'apipkin'
        });

        expect(m).to.equal('apipkin ${formula}');

    });

});

describe('message creation for plurals', function () {
    var msg = new IntlMessageFormat(['I have ', {
            type: 'plural',
            valueName: 'numPeople',
            options: {
                zero : 'zero points',
                one  : 'a point',
                two  : 'two points',
                few  : 'a few points',
                many : 'lots of points',
                other: 'some other amount of points'
            }
        }, '.'], 'ar');

    it('zero', function () {
        var m = msg.format({
            numPeople: 0
        });

        expect(m).to.equal('I have zero points.');
    });

    it('one', function () {
        var m = msg.format({
            numPeople: 1
        });

        expect(m).to.equal('I have a point.');
    });

    it('two', function () {
        var m = msg.format({
            numPeople: 2
        });

        expect(m).to.equal('I have two points.');
    });

    it('few', function () {
        var m = msg.format({
            numPeople: 5
        });

        expect(m).to.equal('I have a few points.');
    });

    it('many', function () {
        var m = msg.format({
            numPeople: 20
        });

        expect(m).to.equal('I have lots of points.');
    });

    it('other', function () {
        var m = msg.format({
            numPeople: 100
        });

        expect(m).to.equal('I have some other amount of points.');
    });

});

describe('locale switching', function () {
    var simple = {
            en: [
                { valueName: 'NAME' },
                ' went to ',
                { valueName: 'CITY' },
                '.'
            ],
            fr: [
                { valueName: 'NAME' },
                ' est ',
                {
                    type: 'gender',
                    valueName: 'gender',
                    options: {
                        female: 'allée',
                        other: 'allé'
                    }
                },
                ' à ',
                { valueName: 'CITY' },
                '.'
            ]
        },

        complex = {
            en: '${TRAVELLERS} went to ${CITY}.',
            fr: [
                '${TRAVELLERS}',
                {
                    type: 'plural',
                    valueName: 'TRAVELLER_COUNT',
                    options: {
                        one: [' est ', {
                            type: 'gender',
                            valueName: 'GENDER',
                            options: {
                                female: 'allée',
                                other: 'allé'
                            }
                        }],
                        other: [' sont ', {
                            type: 'gender',
                            valueName: 'GENDER',
                            options: {
                                female: 'allées',
                                other: 'allés'
                            }
                        }]
                    }
                },
                ' à ',
                '${CITY}',
                '.'
            ]
        },

        maleObj = {
            NAME: 'Tony',
            CITY: 'Paris',
            gender: 'male'
        },
        femaleObj = {
            NAME: 'Jenny',
            CITY: 'Paris',
            gender: 'female'
        },

        maleTravelers = {
            TRAVELLERS: 'Lucas, Tony and Drew',
            TRAVELLER_COUNT: 3,
            GENDER: 'male',
            CITY: 'Paris'
        },

        femaleTravelers = {
            TRAVELLERS: 'Monica',
            TRAVELLER_COUNT: 1,
            GENDER: 'female',
            CITY: 'Paris'
        };

    it('en-US simple', function () {
        var msg = new IntlMessageFormat(simple.en, 'en-US');

        expect(msg.format(maleObj)).to.equal('Tony went to Paris.');

        expect(msg.format(femaleObj)).to.equal('Jenny went to Paris.');
    });

    it('fr-FR simple', function () {
        var msg = new IntlMessageFormat(simple.fr, 'fr-FR');

        expect(msg.format(maleObj)).to.equal('Tony est allé à Paris.');

        expect(msg.format(femaleObj)).to.equal('Jenny est allée à Paris.');
    });

    it('en-US complex', function () {
        var msg = new IntlMessageFormat(complex.en, 'en-US');

        expect(msg.format(maleTravelers)).to.equal('Lucas, Tony and Drew went to Paris.');

        expect(msg.format(femaleTravelers)).to.equal('Monica went to Paris.');
    });

    it('fr-FR complex', function () {
        var msg = new IntlMessageFormat(complex.fr, 'fr-FR');

        expect(msg.format(maleTravelers)).to.equal('Lucas, Tony and Drew sont allés à Paris.');

        expect(msg.format(femaleTravelers)).to.equal('Monica est allée à Paris.');
    });

});

describe('locale switching with counts', function () {

    var messages = {
            en: [{
                    type: 'plural',
                    valueName: 'COMPANY_COUNT',
                    options: {
                       one: 'One company',
                       other: '${#} companies'
                    }
                },
                ' published new books.'
            ],
            ru: [{
                    type: 'plural',
                    valueName: 'COMPANY_COUNT',
                    options: {
                        one: 'Одна компания опубликовала',
                        many: '${#} компаний опубликовали',
                        other: '${#} компаний опубликовали'
                    }
                },
                ' новые книги.'
            ]
        };

    it('en-US', function () {
        var msg = new IntlMessageFormat(messages.en, 'en-US');

        expect(msg.format({COMPANY_COUNT: 0})).to.equal('0 companies published new books.');

        expect(msg.format({COMPANY_COUNT: 1})).to.equal('One company published new books.');

        expect(msg.format({COMPANY_COUNT: 2})).to.equal('2 companies published new books.');

        expect(msg.format({COMPANY_COUNT: 5})).to.equal('5 companies published new books.');

        expect(msg.format({COMPANY_COUNT: 10})).to.equal('10 companies published new books.');
    });

    it('ru-RU', function () {
        var msg = new IntlMessageFormat(messages.ru, 'ru-RU');

        expect(msg.format({COMPANY_COUNT: 0})).to.equal('0 компаний опубликовали новые книги.');

        expect(msg.format({COMPANY_COUNT: 1})).to.equal('Одна компания опубликовала новые книги.');

        expect(msg.format({COMPANY_COUNT: 2})).to.equal('2 компаний опубликовали новые книги.');

        expect(msg.format({COMPANY_COUNT: 5})).to.equal('5 компаний опубликовали новые книги.');

        expect(msg.format({COMPANY_COUNT: 10})).to.equal('10 компаний опубликовали новые книги.');
    });

});

<commit_msg>90+% coverage<commit_after>/*
 * Copyright (c) 2011-2013, Yahoo! Inc.  All rights reserved.
 * Copyrights licensed under the New BSD License.
 * See the accompanying LICENSE file for terms.
 */

/*jshint node:true */
/*global describe,it */
'use strict';

var chai,
    expect,
    IntlMessageFormat;

// This oddity is so that this file can be used for both client-side and
// server-side testing.  (On the client we've already loaded chai and
// IntlMessageFormat.)
if ('function' === typeof require) {

    delete global.IntlMessageFormat;

    chai = require('chai');

    IntlMessageFormat = require('../build/index.en.min.js');

    require('../locale-data/en.js');
    require('../locale-data/ar.js');
    require('../locale-data/pl.js');

}
expect = chai.expect;

describe('message resolvedOptions', function () {

    it('empty options', function () {
        var msg, o, p, pCount = 0;

        msg = new IntlMessageFormat('My name is ${name}');

        o = msg.resolvedOptions();

        for (p in o) {
            if (o.hasOwnProperty(p)) {
                pCount++;
            }
        }

        expect(pCount).to.equal(0);
    });
});

describe('message creation', function () {

    it('simple string formatting', function () {
        var msg, m;
        msg = new IntlMessageFormat('My name is ${first} {last}.');
        m = msg.format({
            first: 'Anthony',
            last: 'Pipkin'
        });
        expect(m).to.equal('My name is Anthony Pipkin.');
    });

    it('simple object formatting', function () {
        var msg, m;

        msg = new IntlMessageFormat(['I have ', 2, ' cars.']);

        m = msg.format();

        expect(m).to.equal('I have 2 cars.');

    });

    it('simple object with post processing tokens', function () {
        var msg, m;

        msg = new IntlMessageFormat(['${', 'company', '}', ' {', 'verb' ,'}.']);

        m = msg.format({
            company: 'Yahoo',
            verb: 'rocks'
        });

        expect(m).to.equal('Yahoo rocks.');

    });

    it ('complex object formatter', function () {
        var msg, m;
        msg = new IntlMessageFormat(['Some text before ', {
            type: 'plural',
            valueName: 'numPeople',
            options: {
                one: 'one',

                few: 'few',

                other: 'Some messages for the default'
            }
        }, ' and text after']);

        m = msg.format({
            numPeople: 20
        });

        expect(m).to.equal("Some text before Some messages for the default and text after");
    });

    it ('complex object formatter with invalid valueName', function () {
        var msg, m;
        msg = new IntlMessageFormat(['Some text before ', {
            type: 'plural',
            valueName: 'numPeople',
            options: {
                one: 'one',

                few: 'few',

                other: 'Some messages for the default'
            }
        }, ' and text after']);

        try {
            m = msg.format({
                jumper: 20
            });
        } catch (e) {
            var err = new ReferenceError('The valueName `numPeople` was not found.');
            expect(e.toString()).to.equal(err.toString());
        }
    });

    it ('complex object formatter with offset', function () {
        var msg, m;
        msg = new IntlMessageFormat(['Some text before ', {
            type: 'plural',
            valueName: 'numPeople',
            offset: 1,
            options: {
                one: 'Some message ${ph} with ${#} value',

                few: ['Optional prefix text for |few| ', {
                    type: 'select',
                    valueName: 'gender',
                    options: {
                        male: 'Text for male option with \' single quotes',
                        female: 'Text for female option with {}',
                        other: 'Text for default'
                    }
                }, ' optional postfix text'],

                other: 'Some messages for the default'

            }
        }, ' and text after'],
            'pl'    // this has the "few" rule that we need
        );
        m = msg.format({
            numPeople: 1,   // offset will move this to "2" so that the "few" group is used
            ph: 'whatever',
            gender: 'male'
        });
        expect(m).to.equal("Some text before Optional prefix text for |few| Text for male option with ' single quotes optional postfix text and text after");
    });

    it('Simple string formatter using a custom formatter for a token', function () {
        var msg, m;
        msg = new IntlMessageFormat('Test formatter d: ${num:d}', null, {
            d: function (val, locale) {
                return +val;
            }
        });
        m = msg.format({
            num: '010'
        });
        expect(m).to.equal('Test formatter d: 10');
    });

    it('Simple string formatter using an inline formatter for a token', function () {
        var msg, m;
        msg = new IntlMessageFormat([{
            valueName: 'str',
            formatter: function (val, locale) {
                return val.toString().split('').reverse().join('');
            }
        }]);
        m = msg.format({
            str: 'aardvark'
        });
        expect(m).to.equal('kravdraa');
    });

    it('Simple string formatter using a nonexistent formatter for a token', function () {
        var msg, m;
        msg = new IntlMessageFormat('Test formatter foo: ${num:foo}', null, {
            d: function (val, locale) {
                return +val;
            }
        });
        m = msg.format({
            num: '010'
        });
        expect(m).to.equal('Test formatter foo: 010');
    });

    it('Custom formatters with hidden inheritance', function () {
        var msg, m,
            Formatters = function () {
                this.d = function (val, locale) {
                    return val + '030';
                };
            },
            CustomFormatters = function () {
                this.f = function (val, locale) {
                    return val + '080';
                };
            };

        CustomFormatters.prototype = Formatters;
        CustomFormatters.prototype.constructor = CustomFormatters;

        msg = new IntlMessageFormat('d: ${num:d} / f: ${num:f}', null, new CustomFormatters());

        m = msg.format({
            num: 0
        });

        expect(m).to.equal('d: 0 / f: 0080');
    });

    it('broken pattern', function () {
       var msg, m;

        msg = new IntlMessageFormat('${name} ${formula}');

        msg.pattern = '${name} ${formula}';

        m = msg.format({
            name: 'apipkin'
        });

        expect(m).to.equal('apipkin ${formula}');

    });

});

describe('message creation for plurals', function () {
    var msg = new IntlMessageFormat(['I have ', {
            type: 'plural',
            valueName: 'numPeople',
            options: {
                zero : 'zero points',
                one  : 'a point',
                two  : 'two points',
                few  : 'a few points',
                many : 'lots of points',
                other: 'some other amount of points'
            }
        }, '.'], 'ar');

    it('zero', function () {
        var m = msg.format({
            numPeople: 0
        });

        expect(m).to.equal('I have zero points.');
    });

    it('one', function () {
        var m = msg.format({
            numPeople: 1
        });

        expect(m).to.equal('I have a point.');
    });

    it('two', function () {
        var m = msg.format({
            numPeople: 2
        });

        expect(m).to.equal('I have two points.');
    });

    it('few', function () {
        var m = msg.format({
            numPeople: 5
        });

        expect(m).to.equal('I have a few points.');
    });

    it('many', function () {
        var m = msg.format({
            numPeople: 20
        });

        expect(m).to.equal('I have lots of points.');
    });

    it('other', function () {
        var m = msg.format({
            numPeople: 100
        });

        expect(m).to.equal('I have some other amount of points.');
    });
});

describe('locale switching', function () {
    var simple = {
            en: [
                { valueName: 'NAME' },
                ' went to ',
                { valueName: 'CITY' },
                '.'
            ],
            fr: [
                { valueName: 'NAME' },
                ' est ',
                {
                    type: 'gender',
                    valueName: 'gender',
                    options: {
                        female: 'allée',
                        other: 'allé'
                    }
                },
                ' à ',
                { valueName: 'CITY' },
                '.'
            ]
        },

        complex = {
            en: '${TRAVELLERS} went to ${CITY}.',
            fr: [
                '${TRAVELLERS}',
                {
                    type: 'plural',
                    valueName: 'TRAVELLER_COUNT',
                    options: {
                        one: [' est ', {
                            type: 'gender',
                            valueName: 'GENDER',
                            options: {
                                female: 'allée',
                                other: 'allé'
                            }
                        }],
                        other: [' sont ', {
                            type: 'gender',
                            valueName: 'GENDER',
                            options: {
                                female: 'allées',
                                other: 'allés'
                            }
                        }]
                    }
                },
                ' à ',
                '${CITY}',
                '.'
            ]
        },

        maleObj = {
            NAME: 'Tony',
            CITY: 'Paris',
            gender: 'male'
        },
        femaleObj = {
            NAME: 'Jenny',
            CITY: 'Paris',
            gender: 'female'
        },

        maleTravelers = {
            TRAVELLERS: 'Lucas, Tony and Drew',
            TRAVELLER_COUNT: 3,
            GENDER: 'male',
            CITY: 'Paris'
        },

        femaleTravelers = {
            TRAVELLERS: 'Monica',
            TRAVELLER_COUNT: 1,
            GENDER: 'female',
            CITY: 'Paris'
        };

    it('en-US simple', function () {
        var msg = new IntlMessageFormat(simple.en, 'en-US');

        expect(msg.format(maleObj)).to.equal('Tony went to Paris.');

        expect(msg.format(femaleObj)).to.equal('Jenny went to Paris.');
    });

    it('fr-FR simple', function () {
        var msg = new IntlMessageFormat(simple.fr, 'fr-FR');

        expect(msg.format(maleObj)).to.equal('Tony est allé à Paris.');

        expect(msg.format(femaleObj)).to.equal('Jenny est allée à Paris.');
    });

    it('en-US complex', function () {
        var msg = new IntlMessageFormat(complex.en, 'en-US');

        expect(msg.format(maleTravelers)).to.equal('Lucas, Tony and Drew went to Paris.');

        expect(msg.format(femaleTravelers)).to.equal('Monica went to Paris.');
    });

    it('fr-FR complex', function () {
        var msg = new IntlMessageFormat(complex.fr, 'fr-FR');

        expect(msg.format(maleTravelers)).to.equal('Lucas, Tony and Drew sont allés à Paris.');

        expect(msg.format(femaleTravelers)).to.equal('Monica est allée à Paris.');
    });

});

describe('locale switching with counts', function () {

    var messages = {
            en: [{
                    type: 'plural',
                    valueName: 'COMPANY_COUNT',
                    options: {
                       one: 'One company',
                       other: '${#} companies'
                    }
                },
                ' published new books.'
            ],
            ru: [{
                    type: 'plural',
                    valueName: 'COMPANY_COUNT',
                    options: {
                        one: 'Одна компания опубликовала',
                        many: '${#} компаний опубликовали',
                        other: '${#} компаний опубликовали'
                    }
                },
                ' новые книги.'
            ]
        };

    it('en-US', function () {
        var msg = new IntlMessageFormat(messages.en, 'en-US');

        expect(msg.format({COMPANY_COUNT: 0})).to.equal('0 companies published new books.');

        expect(msg.format({COMPANY_COUNT: 1})).to.equal('One company published new books.');

        expect(msg.format({COMPANY_COUNT: 2})).to.equal('2 companies published new books.');

        expect(msg.format({COMPANY_COUNT: 5})).to.equal('5 companies published new books.');

        expect(msg.format({COMPANY_COUNT: 10})).to.equal('10 companies published new books.');
    });

    it('ru-RU', function () {
        var msg = new IntlMessageFormat(messages.ru, 'ru-RU');

        expect(msg.format({COMPANY_COUNT: 0})).to.equal('0 компаний опубликовали новые книги.');

        expect(msg.format({COMPANY_COUNT: 1})).to.equal('Одна компания опубликовала новые книги.');

        expect(msg.format({COMPANY_COUNT: 2})).to.equal('2 компаний опубликовали новые книги.');

        expect(msg.format({COMPANY_COUNT: 5})).to.equal('5 компаний опубликовали новые книги.');

        expect(msg.format({COMPANY_COUNT: 10})).to.equal('10 компаний опубликовали новые книги.');
    });

});

//------------------------------------------------
//
//====== CAUTION: PURGING BEYOND THIS POINT ======
//
//------------------------------------------------

describe('no locale provided', function () {
    it('no locale', function () {
        try {
            IntlMessageFormat.__purge();

            var msg = new IntlMessageFormat(['I have ', {
                type: 'plural',
                valueName: 'NUM_BOOKS',
                options: {
                    one: '1 book',
                    other: '${#} books'
                }
            }, '.']);

            var m = msg.format({ NUM_BOOKS: 2 });

            // always fail if we didn't throw
            expect(false).to.equal(true);

        } catch (e) {
            var err = new ReferenceError('No locale data has been provided for this object yet.');
            expect(e.toString()).to.equal(err.toString());
        }
    });
});

describe('no default', function () {
    it('blind switching', function () {
        var msg = new IntlMessageFormat([{
                type: 'plural',
                valueName: 'COMPANY_COUNT',
                options: {
                   one: 'One company',
                   other: '${#} companies'
                }
            },
            ' published new books.'
        ]);

        // let's set the locale to something witout data
        IntlMessageFormat.__addLocaleData({locale: 'fu-baz'});
        msg.locale = 'fu-baz';

        var m = msg.format({ COMPANY_COUNT: 1});

        expect(m).to.equal('1 companies published new books.');
    });

    it('update locale', function () {
        IntlMessageFormat.__purge();

        // let's set the locale to something witout data
        IntlMessageFormat.__addLocaleData({
            locale: 'fu-baz',
            messageformat: {
                pluralFunction: function (count) { return null; }
            }
        });

        var msg = new IntlMessageFormat([{
                type: 'plural',
                valueName: 'COMPANY_COUNT',
                options: {
                   one: 'One company',
                   other: '${#} companies'
                }
            },
            ' published new books.'
        ]);

        var m = msg.format({ COMPANY_COUNT: 1});

        expect(m).to.equal('1 companies published new books.');
    });
});

<|endoftext|>


<commit_before>// ==UserScript==
// @name sevichat
// @namespace http://keyboardfire.com/
// @author SE user Doorknob <andy@keyboardfire.com>
// @version 0.1
// @description sevichat == SE vi chat; vim-esque keyboard shortcuts for Stack Exchange chat
// @grant none
// @copyright MIT
// @include *://chat.stackoverflow.com/*
// @include *://chat.stackexchange.com/*
// @include *://chat.meta.stackexchange.com/*
// ==/UserScript==

// this will inject the code as a <script> element, because Safari doesn't seem
// to be using the page's jQuery properly
function withJQuery(f) {
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.textContent = '(' + f + ')(jQuery)';
    document.head.appendChild(script);
}
withJQuery(sevichat);

function sevichat($) {
    var input = $('#input');

    var currentMsg;
    var setCurrentMsg = function(m) {
        if (currentMsg) currentMsg.css('background-color', '');
        currentMsg = m;
        if (m) m.css('background-color', 'rgba(0, 255, 0, 0.1)');
    };

    var clickMenuItem = function(item) {
        currentMsg.find('.action-link').click();
        var intr = setInterval(function() {
            var popup = $('.popup');
            if (popup.length) {
                popup.find(item).click();
                clearInterval(intr);
            }
        }, 10);
    };

    input.keydown(function(e) {
        if (!currentMsg) {
            // ctrl+O
            if (e.which == 79 && e.ctrlKey) {
                e.preventDefault();
                setCurrentMsg($('.message:last'));
            }
        } else {
            e.preventDefault();
            switch (e.which) {
                case 68:  // d
                    if (confirm('ya sure about that?')) {
                        $.post('http://chat.stackexchange.com/messages/' +
                            currentMsg.attr('id').split('-')[1] + '/delete', {
                                fkey: fkey().fkey
                            });
                    }
                    setCurrentMsg();
                    break;
                case 69:  // e
                    clickMenuItem('.edit');
                    setCurrentMsg();
                    break;
                case 70:  // f
                    currentMsg.find('.flags .vote').click();
                    setCurrentMsg();
                    break;
                case 74:  // j
                    var next = currentMsg.next('.message');
                    if (!next.length) {
                        next = currentMsg.closest('.monologue')
                            .nextAll('.monologue').eq(0).find('.message:first');
                    }
                    if (next.length) setCurrentMsg(next);
                    break;
                case 75:  // k
                    var prev = currentMsg.prev('.message');
                    if (!prev.length) {
                        prev = currentMsg.closest('.monologue')
                            .prevAll('.monologue').eq(0).find('.message:last');
                    }
                    if (prev.length) setCurrentMsg(prev);
                    break;
                case 80:  // p
                    clickMenuItem('.owner-star');
                    setCurrentMsg();
                    break;
                case 82:  // r
                    currentMsg.find('.newreply').click();
                    setCurrentMsg();
                    break;
                case 83:  // s
                    currentMsg.find('.stars:first .vote').click();
                    setCurrentMsg();
                    break;
                case 89:  // y
                    prompt('hit ctrl+c', location.origin +
                        currentMsg.find('.action-link').attr('href'));
                    setCurrentMsg();
                    break;
            }
        }
    });

    input.blur(function(e) {
        setCurrentMsg();
        if ($('#cancel-editing-button').css('display') !== 'none') {
            $('#cancel-editing-button').click();
        }
    });
}
<commit_msg>Scroll around correctly<commit_after>// ==UserScript==
// @name sevichat
// @namespace http://keyboardfire.com/
// @author SE user Doorknob <andy@keyboardfire.com>
// @version 0.1
// @description sevichat == SE vi chat; vim-esque keyboard shortcuts for Stack Exchange chat
// @grant none
// @copyright MIT
// @include *://chat.stackoverflow.com/*
// @include *://chat.stackexchange.com/*
// @include *://chat.meta.stackexchange.com/*
// ==/UserScript==

// this will inject the code as a <script> element, because Safari doesn't seem
// to be using the page's jQuery properly
function withJQuery(f) {
    var script = document.createElement('script');
    script.type = 'text/javascript';
    script.textContent = '(' + f + ')(jQuery)';
    document.head.appendChild(script);
}
withJQuery(sevichat);

function sevichat($) {
    var input = $('#input');

    var currentMsg;
    var setCurrentMsg = function(m) {
        if (currentMsg) currentMsg.css('background-color', '');
        currentMsg = m;
        if (m) {
            m.css('background-color', 'rgba(0, 255, 0, 0.1)');
            document.body.scrollTop = m[0].offsetTop;
        }
    };

    var clickMenuItem = function(item) {
        currentMsg.find('.action-link').click();
        var intr = setInterval(function() {
            var popup = $('.popup');
            if (popup.length) {
                popup.find(item).click();
                clearInterval(intr);
            }
        }, 10);
    };

    input.keydown(function(e) {
        if (!currentMsg) {
            // ctrl+O
            if (e.which == 79 && e.ctrlKey) {
                e.preventDefault();
                setCurrentMsg($('.message:last'));
            }
        } else {
            e.preventDefault();
            switch (e.which) {
                case 68:  // d
                    if (confirm('ya sure about that?')) {
                        $.post('http://chat.stackexchange.com/messages/' +
                            currentMsg.attr('id').split('-')[1] + '/delete', {
                                fkey: fkey().fkey
                            });
                    }
                    setCurrentMsg();
                    break;
                case 69:  // e
                    clickMenuItem('.edit');
                    setCurrentMsg();
                    break;
                case 70:  // f
                    currentMsg.find('.flags .vote').click();
                    setCurrentMsg();
                    break;
                case 74:  // j
                    var next = currentMsg.next('.message');
                    if (!next.length) {
                        next = currentMsg.closest('.monologue')
                            .nextAll('.monologue').eq(0).find('.message:first');
                    }
                    if (next.length) setCurrentMsg(next);
                    break;
                case 75:  // k
                    var prev = currentMsg.prev('.message');
                    if (!prev.length) {
                        prev = currentMsg.closest('.monologue')
                            .prevAll('.monologue').eq(0).find('.message:last');
                    }
                    if (prev.length) setCurrentMsg(prev);
                    break;
                case 80:  // p
                    clickMenuItem('.owner-star');
                    setCurrentMsg();
                    break;
                case 82:  // r
                    currentMsg.find('.newreply').click();
                    setCurrentMsg();
                    break;
                case 83:  // s
                    currentMsg.find('.stars:first .vote').click();
                    setCurrentMsg();
                    break;
                case 89:  // y
                    prompt('hit ctrl+c', location.origin +
                        currentMsg.find('.action-link').attr('href'));
                    setCurrentMsg();
                    break;
            }
        }
    });

    input.blur(function(e) {
        setCurrentMsg();
        if ($('#cancel-editing-button').css('display') !== 'none') {
            $('#cancel-editing-button').click();
        }
    });
}
<|endoftext|>


<commit_before>import React, { useEffect } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import DocumentTitle from 'react-document-title';
import * as duck from '../../duck';
import * as utils from '../../utils';
import Countries from '../Countries';
import Image from './components/Image';

function Country({ weather, country, countries, fetch }) {
    const { title, label, fahrenheit, timezone, date } = utils.getWeather(
        weather,
        country,
    );
    useEffect(() => {
        fetch(country);
    }, [country]);

    return (
        <DocumentTitle title={`Weather for ${country}`}>

                <button
                    className="refresh"
                    onClick={() => fetch(country, { cache: false })}
                >
                    Refresh
                </button>

                    <Image src={utils.getFilename(country)} alt={country} />

                        {title} at{' '}
                        {timezone
                            ? date.add(timezone, 'seconds').format('HH:mm:ss')
                            : String.fromCharCode(8212)}

{label}

                    <Countries country={country} countries={countries} />

        </DocumentTitle>
    );
}

Country.propTypes = {
    weather: PropTypes.array.isRequired,
    country: PropTypes.string.isRequired,
    countries: PropTypes.array.isRequired,
    fetch: PropTypes.func.isRequired,
};

Country.defaultProps = { weather: null };

function mapStateToProps(state) {
    return state;
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators(duck.actions, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(Country);
<commit_msg>Fixed title<commit_after>import React, { useEffect } from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import PropTypes from 'prop-types';
import DocumentTitle from 'react-document-title';
import * as duck from '../../duck';
import * as utils from '../../utils';
import Countries from '../Countries';
import Image from './components/Image';

function Country({ weather, country, countries, fetch }) {
    const { title, label, fahrenheit, timezone, date } = utils.getWeather(
        weather,
        country,
    );
    useEffect(() => {
        fetch(country);
    }, [country]);

    return (
        <DocumentTitle title={`Weather for ${country.replace('-', ' ')}`}>

                <button
                    className="refresh"
                    onClick={() => fetch(country, { cache: false })}
                >
                    Refresh
                </button>

                    <Image src={utils.getFilename(country)} alt={country} />

                        {title} at{' '}
                        {timezone
                            ? date.add(timezone, 'seconds').format('HH:mm:ss')
                            : String.fromCharCode(8212)}

{label}

                    <Countries country={country} countries={countries} />

        </DocumentTitle>
    );
}

Country.propTypes = {
    weather: PropTypes.array.isRequired,
    country: PropTypes.string.isRequired,
    countries: PropTypes.array.isRequired,
    fetch: PropTypes.func.isRequired,
};

Country.defaultProps = { weather: null };

function mapStateToProps(state) {
    return state;
}

function mapDispatchToProps(dispatch) {
    return bindActionCreators(duck.actions, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(Country);
<|endoftext|>


<commit_before>//
// shock-trigger.js
//
// Entity script meant to be attached to a box entity.
//

var TRIGGER_CHANNEL = "shock-trigger-channel";

(function () {
    var inside = false;
    var timer = 0.0;
    var entityID;
    this.preload = function (id) {
        entityID = id;
        Script.update.connect(this.update);
    };
    this.enterEntity = function (id) {
        inside = true;
        this.sendUpdate();
    };
    this.leaveEntity = function (id) {
        inside = false;
        this.sendUpdate();
    };
    this.update = function (dt) {
        timer += dt;
        if (timer > 1) {
            sendUpdate();
            timer = 0;
        }
    };
    function sendUpdate() {
        Messages.sendMessage(TRIGGER_CHANNEL, JSON.stringify({ inside: inside, entityID: entityID }));
        print("sendMessage inside = " + inside + ", entityID = " + entityID);
    };
    this.unload = function (entityID) {
        Script.update.disconnect(this.update);
    };
})
<commit_msg>Removed entity trigger print spam.<commit_after>//
// shock-trigger.js
//
// Entity script meant to be attached to a box entity.
//

var TRIGGER_CHANNEL = "shock-trigger-channel";

(function () {
    var inside = false;
    var timer = 0.0;
    var entityID;
    this.preload = function (id) {
        entityID = id;
        Script.update.connect(this.update);
    };
    this.enterEntity = function (id) {
        inside = true;
        this.sendUpdate();
    };
    this.leaveEntity = function (id) {
        inside = false;
        this.sendUpdate();
    };
    this.update = function (dt) {
        timer += dt;
        if (timer > 1) {
            sendUpdate();
            timer = 0;
        }
    };
    function sendUpdate() {
        Messages.sendMessage(TRIGGER_CHANNEL, JSON.stringify({ inside: inside, entityID: entityID }));
    };
    this.unload = function (entityID) {
        Script.update.disconnect(this.update);
    };
})
<|endoftext|>


<commit_before>'use strict';

var td              = require('testdouble');

var ui              = require('../../../lib/utils/ui');
var expect          = require('../../helpers/expect');
var Promise         = require('ember-cli/lib/ext/promise');

var BuildCmd        = require('../../../lib/commands/build');
var BuildTask       = require('../../../lib/tasks/ember-build');
var CdvBuildTask    = require('../../../lib/tasks/cordova-build');
var HookTask        = require('../../../lib/tasks/run-hook');
var PlatformTask    = require('../../../lib/tasks/validate/platform');

var mockProject   = require('../../fixtures/ember-cordova-mock/project');
var mockAnalytics = require('../../fixtures/ember-cordova-mock/analytics');
var parsePlatformOpts = require('../../../lib/utils/parse-platform-opts');

describe('Build Command', function() {
  var build;

  beforeEach(function() {
    var project = mockProject.project;
    project.config = function() {
      return {
        locationType: 'hash'
      };
    }

    build = new BuildCmd({
      project: project,
      ui: mockProject.ui
    });
    build.analytics = mockAnalytics;
  });

  afterEach(function() {
    td.reset();
  });

  context('when locationType is hash', function() {
    let tasks;
    let cordovaOptions;

    beforeEach(function() {
      mockTasks();
    });

    function mockTasks() {
      tasks = [];

      td.replace(PlatformTask.prototype, 'run', function() {
        tasks.push('check-platform');
        return Promise.resolve();
      });

      td.replace(HookTask.prototype, 'run', function(hookName) {
        tasks.push('hook ' + hookName);
        return Promise.resolve();
      });

      td.replace(BuildTask.prototype, 'run', function() {
        return Promise.resolve();
      });

      td.replace(CdvBuildTask.prototype, 'run', function(_cordovaOptions) {
        cordovaOptions = _cordovaOptions;

        tasks.push('cordova-build');
        return Promise.resolve();
      });
    }

    it('exits cleanly', function() {
      return expect(function() {
        build.run({});
      }).not.to.throw(Error);
    });

    it('runs tasks in the correct order', function() {
      return build.run({})
        .then(function() {
          //h-t ember-electron for the pattern
          expect(tasks).to.deep.equal([
            'check-platform',
            'hook beforeBuild',
            'cordova-build',
            'hook afterBuild'
          ]);
        });
    });

    context('when passedPlatform is ios', function() {
      it('platform eq ios', function() {
        let passedPlatform = 'ios';

        return build.run({
          platform: passedPlatform
        }).then(function() {
          expect(cordovaOptions.platform).to.equal(passedPlatform);
        });
      });
    });
    context('when passedPlatform is android', function() {
      it('platform eq android', function() {
        let passedPlatform = 'android';

        return build.run({
          platform: passedPlatform
        }).then(function() {
          expect(cordovaOptions.platform).to.equal(passedPlatform);
        });
      });
    });

    describe('isRelease', function() {
      context('when release is false', function() {
        it('isRelease eq false', function() {
          let passedPlatform = 'ios';
          let passedRelease = false;

          return build.run({
            platform: passedPlatform,
            isRelease: passedRelease,
          }).then(function() {
            expect(cordovaOptions.isRelease).to.equal(passedRelease);
          });
        });
      });
      context('when release is true', function() {
        it('isRelease eq true', function() {
          let passedPlatform = 'ios';
          let passedRelease = true;

          return build.run({
            platform: passedPlatform,
            isRelease: passedRelease,
          }).then(function() {
            expect(cordovaOptions.isRelease).to.equal(passedRelease);
          });
        });
      });
    });

    describe('isEmulator', function() {
      context('when device is false', function() {
        it('isEmulator eq true', function() {
          let passedPlatform = 'ios';
          let passedDevice = false;

          return build.run({
            platform: passedPlatform,
            isEmulator: passedDevice,
          }).then(function() {
            expect(cordovaOptions.isEmulator).to.equal(passedDevice);
          });
        });
      });
      context('when device is true', function() {
        it('isEmulator eq false', function() {
          let passedPlatform = 'ios';
          let passedDevice = true;

          return build.run({
            platform: passedPlatform,
            isEmulator: passedDevice,
          }).then(function() {
            expect(cordovaOptions.isEmulator).to.equal(passedDevice);
          });
        });
      });
    });

    describe('buildConfig', function() {
      context('when not passed', function() {
        it('does not append buildConfig to options', function() {
          let passedPlatform = 'ios';
          let passedBuildConfig = undefined;

          return build.run({
            platform: passedPlatform,
          }).then(function() {
            expect(cordovaOptions.buildConfig).to.equal(passedBuildConfig);
          });
        });
      });
      context('when buildConfig is passed', function() {
        it('appends buildConfig options to options', function() {
          let passedPlatform = 'ios';
          let passedBuildConfig = '/foo';

          return build.run({
            platform: passedPlatform,
            buildConfig: passedBuildConfig,
          }).then(function() {
            expect(cordovaOptions.buildConfig).to.equal(passedBuildConfig);
          });
        });
      });
    });

    describe('platformOpts', () => {
      context('when platform is ios', function() {
        it('passes ios options to CdvBuildTask', function()  {
          let passedPlatform = 'ios';
          let platformOpts = parsePlatformOpts(
            cordovaOptions.platform,
            cordovaOptions
          );

          return build.run({
            platform: passedPlatform,
            platformOpts: platformOpts
          }).then(function() {
            expect('codeSignIdentity' in cordovaOptions.platformOpts)
            .to.equal('codeSignIdentity' in platformOpts);
          });
        });

        it('filters out android options', function() {
          let passedPlatform = 'ios';
          let platformOpts = parsePlatformOpts(
            cordovaOptions.platform,
            cordovaOptions
          );

          return build.run({
            platform: passedPlatform,
            platformOpts: platformOpts
          }).then(function() {
            expect('alias' in cordovaOptions.platformOpts)
            .to.equal('alias' in platformOpts);
          });
        });
      });

      context('when platform is android', function() {
        it('passes android options to CdvBuildTask', function() {
          let passedPlatform = 'android';
          let platformOpts = parsePlatformOpts(
            cordovaOptions.platform,
            cordovaOptions
          );

          return build.run({
            platform: passedPlatform,
            platformOpts: platformOpts
          }).then(function() {
            expect('alias' in cordovaOptions.platformOpts)
            .to.equal('alias' in platformOpts);
          });
        });

        it('filters out ios options', function() {
          let passedPlatform = 'android';
          let platformOpts = parsePlatformOpts(
            cordovaOptions.platform,
            cordovaOptions
          );

          return build.run({
            platform: passedPlatform,
            platformOpts: platformOpts
          }).then(function() {
            expect('codeSignIdentity' in cordovaOptions.platformOpts)
            .to.equal('codeSignIdentity' in platformOpts);
          });
        });
      });
    });
  });

  context('when locationType is not hash', function() {
    beforeEach(function() {
      build.project.config = function() {
        return {
          locationType: 'auto'
        };
      };

      td.replace(ui, 'writeLine',  function() {
        throw new Error('Exit Called');
      });

    });

    it('throws', function() {
      return expect(function() {
        build.run({});
      }).to.throw(Error);
    });
  });
});
<commit_msg>fix(build-test): reserved words removed<commit_after>'use strict';

var td              = require('testdouble');

var ui              = require('../../../lib/utils/ui');
var expect          = require('../../helpers/expect');
var Promise         = require('ember-cli/lib/ext/promise');

var BuildCmd        = require('../../../lib/commands/build');
var BuildTask       = require('../../../lib/tasks/ember-build');
var CdvBuildTask    = require('../../../lib/tasks/cordova-build');
var HookTask        = require('../../../lib/tasks/run-hook');
var PlatformTask    = require('../../../lib/tasks/validate/platform');

var mockProject   = require('../../fixtures/ember-cordova-mock/project');
var mockAnalytics = require('../../fixtures/ember-cordova-mock/analytics');
var parsePlatformOpts = require('../../../lib/utils/parse-platform-opts');

describe('Build Command', function() {
  var build;

  beforeEach(function() {
    var project = mockProject.project;
    project.config = function() {
      return {
        locationType: 'hash'
      };
    }

    build = new BuildCmd({
      project: project,
      ui: mockProject.ui
    });
    build.analytics = mockAnalytics;
  });

  afterEach(function() {
    td.reset();
  });

  context('when locationType is hash', function() {
    var tasks;
    var cordovaOptions;

    beforeEach(function() {
      mockTasks();
    });

    function mockTasks() {
      tasks = [];

      td.replace(PlatformTask.prototype, 'run', function() {
        tasks.push('check-platform');
        return Promise.resolve();
      });

      td.replace(HookTask.prototype, 'run', function(hookName) {
        tasks.push('hook ' + hookName);
        return Promise.resolve();
      });

      td.replace(BuildTask.prototype, 'run', function() {
        return Promise.resolve();
      });

      td.replace(CdvBuildTask.prototype, 'run', function(_cordovaOptions) {
        cordovaOptions = _cordovaOptions;

        tasks.push('cordova-build');
        return Promise.resolve();
      });
    }

    it('exits cleanly', function() {
      return expect(function() {
        build.run({});
      }).not.to.throw(Error);
    });

    it('runs tasks in the correct order', function() {
      return build.run({})
        .then(function() {
          //h-t ember-electron for the pattern
          expect(tasks).to.deep.equal([
            'check-platform',
            'hook beforeBuild',
            'cordova-build',
            'hook afterBuild'
          ]);
        });
    });

    context('when passedPlatform is ios', function() {
      it('platform eq ios', function() {
        var passedPlatform = 'ios';

        return build.run({
          platform: passedPlatform
        }).then(function() {
          expect(cordovaOptions.platform).to.equal(passedPlatform);
        });
      });
    });
    context('when passedPlatform is android', function() {
      it('platform eq android', function() {
        var passedPlatform = 'android';

        return build.run({
          platform: passedPlatform
        }).then(function() {
          expect(cordovaOptions.platform).to.equal(passedPlatform);
        });
      });
    });

    describe('isRelease', function() {
      context('when release is false', function() {
        it('isRelease eq false', function() {
          var passedPlatform = 'ios';
          var passedRelease = false;

          return build.run({
            platform: passedPlatform,
            isRelease: passedRelease,
          }).then(function() {
            expect(cordovaOptions.isRelease).to.equal(passedRelease);
          });
        });
      });
      context('when release is true', function() {
        it('isRelease eq true', function() {
          var passedPlatform = 'ios';
          var passedRelease = true;

          return build.run({
            platform: passedPlatform,
            isRelease: passedRelease,
          }).then(function() {
            expect(cordovaOptions.isRelease).to.equal(passedRelease);
          });
        });
      });
    });

    describe('isEmulator', function() {
      context('when device is false', function() {
        it('isEmulator eq true', function() {
          var passedPlatform = 'ios';
          var passedDevice = false;

          return build.run({
            platform: passedPlatform,
            isEmulator: passedDevice,
          }).then(function() {
            expect(cordovaOptions.isEmulator).to.equal(passedDevice);
          });
        });
      });
      context('when device is true', function() {
        it('isEmulator eq false', function() {
          var passedPlatform = 'ios';
          var passedDevice = true;

          return build.run({
            platform: passedPlatform,
            isEmulator: passedDevice,
          }).then(function() {
            expect(cordovaOptions.isEmulator).to.equal(passedDevice);
          });
        });
      });
    });

    describe('buildConfig', function() {
      context('when not passed', function() {
        it('does not append buildConfig to options', function() {
          var passedPlatform = 'ios';
          var passedBuildConfig = undefined;

          return build.run({
            platform: passedPlatform,
          }).then(function() {
            expect(cordovaOptions.buildConfig).to.equal(passedBuildConfig);
          });
        });
      });
      context('when buildConfig is passed', function() {
        it('appends buildConfig options to options', function() {
          var passedPlatform = 'ios';
          var passedBuildConfig = '/foo';

          return build.run({
            platform: passedPlatform,
            buildConfig: passedBuildConfig,
          }).then(function() {
            expect(cordovaOptions.buildConfig).to.equal(passedBuildConfig);
          });
        });
      });
    });

    describe('platformOpts', () => {
      context('when platform is ios', function() {
        it('passes ios options to CdvBuildTask', function()  {
          var passedPlatform = 'ios';
          var platformOpts = parsePlatformOpts(
            cordovaOptions.platform,
            cordovaOptions
          );

          return build.run({
            platform: passedPlatform,
            platformOpts: platformOpts
          }).then(function() {
            expect('codeSignIdentity' in cordovaOptions.platformOpts)
            .to.equal('codeSignIdentity' in platformOpts);
          });
        });

        it('filters out android options', function() {
          var passedPlatform = 'ios';
          var platformOpts = parsePlatformOpts(
            cordovaOptions.platform,
            cordovaOptions
          );

          return build.run({
            platform: passedPlatform,
            platformOpts: platformOpts
          }).then(function() {
            expect('alias' in cordovaOptions.platformOpts)
            .to.equal('alias' in platformOpts);
          });
        });
      });

      context('when platform is android', function() {
        it('passes android options to CdvBuildTask', function() {
          var passedPlatform = 'android';
          var platformOpts = parsePlatformOpts(
            cordovaOptions.platform,
            cordovaOptions
          );

          return build.run({
            platform: passedPlatform,
            platformOpts: platformOpts
          }).then(function() {
            expect('alias' in cordovaOptions.platformOpts)
            .to.equal('alias' in platformOpts);
          });
        });

        it('filters out ios options', function() {
          var passedPlatform = 'android';
          var platformOpts = parsePlatformOpts(
            cordovaOptions.platform,
            cordovaOptions
          );

          return build.run({
            platform: passedPlatform,
            platformOpts: platformOpts
          }).then(function() {
            expect('codeSignIdentity' in cordovaOptions.platformOpts)
            .to.equal('codeSignIdentity' in platformOpts);
          });
        });
      });
    });
  });

  context('when locationType is not hash', function() {
    beforeEach(function() {
      build.project.config = function() {
        return {
          locationType: 'auto'
        };
      };

      td.replace(ui, 'writeLine',  function() {
        throw new Error('Exit Called');
      });

    });

    it('throws', function() {
      return expect(function() {
        build.run({});
      }).to.throw(Error);
    });
  });
});
<|endoftext|>


<commit_before>/**
 * Module dependencies
 */

var nodepath = require('path');
var REPL = require('repl');
var stream = require('stream');
var _ = require('@sailshq/lodash');
var chalk = require('chalk');
var CaptainsLog = require('captains-log');

var rconf = require('../lib/app/configuration/rc')();
var Sails = require('../lib/app');
var SharedErrorHelpers = require('../errors');
var readReplHistoryAndStartTranscribing = require('./private/read-repl-history-and-start-transcribing');

/**
 * `sails console`
 *
 * Enter the interactive console (aka REPL) for the app
 * in our working directory.  This is just like the default
 * Node REPL except that it starts with the Sails app in the
 * current directory lifted, and with console history enabled
 * (i.e. so you can press up arrow to browse and potentially
 *  replay commands from past runs)
 *
 * @stability 3
 * @see http://sailsjs.com/documentation/reference/command-line-interface/sails-console
 * ------------------------------------------------------------------------
 * This lifts the Sails app in the current working directory, then uses
 * the core `repl` package to spin up an interactive console.
 *
 * Note that, if `--dontLift` was set, then `sails.load()` will be used
 * instead. (By default, the `sails console` cmd runs `sails.lift()`.)
 * ------------------------------------------------------------------------
 */

module.exports = function() {

  // Get a temporary logger just for use in `sails console`.
  // > This is so that logging levels are configurable, even when a
  // > Sails app hasn't been loaded yet.
  var cliLogger = CaptainsLog(rconf.log);

  // Now grab our dictionary of configuration overrides to pass in
  // momentarily when we lift (or load) our Sails app.  This is the
  // dictionary of configuration settings built from `.sailsrc` file(s),
  // command-line options, and environment variables.
  // (No need to clone, since, even through we're modifying it below,
  //  it's not being used anywhere else.)
  var configOverrides = rconf;

  // Then tweak this configuration to make sure we always disable
  // the ASCII ship.  It just doesn't look good in the REPL.
  if (!_.isObject(configOverrides.log)) {
    configOverrides.log = {};
  }
  configOverrides.log.noShip = true;

  // Determine whether to use the local or global Sails install.
  var sailsApp = (function _determineAppropriateSailsAppInstance(){

    // Use the app's locally-installed Sails dependency (in `node_modules/sails`),
    // assuming it's extant and valid.
    // > Note that we always assume the current working directory to be the
    // > root directory of the app.
    var appPath = process.cwd();
    var localSailsPath = nodepath.resolve(appPath, 'node_modules/sails');
    if (Sails.isLocalSailsValid(localSailsPath, appPath)) {
      cliLogger.verbose('Using locally-installed Sails.');
      cliLogger.silly('(which is located at `'+localSailsPath+'`)');
      return require(localSailsPath);
    }// --•

    // Otherwise, since no workable locally-installed Sails exists,
    // run the app using the currently running version of Sails.
    // > This is probably always the global install.
    cliLogger.info('No local Sails install detected; using globally-installed Sails.');

    return Sails();

  })();

  console.log();
  if (configOverrides.dontLift) {
    cliLogger.info(chalk.blue('Loading app in interactive mode...'));
    cliLogger.info(chalk.gray('Sails is not listening for requests (since `dontLift` was enabled).'));
    cliLogger.info(chalk.gray('You still have access to your models, helpers, and `sails`.'));
  }
  else {
    cliLogger.info(chalk.blue('Starting app in interactive mode...'));
  }
  console.log();

  // Lift (or load) Sails
  (function _loadOrLift(proceed){

    // If `--dontLift` was set, then use `.load()` instead.
    if (configOverrides.dontLift) {
      sailsApp.load(configOverrides, proceed);
    }
    // Otherwise, go with the default behavior (`.lift()`)
    else {
      sailsApp.lift(configOverrides, proceed);
    }

  })(function afterwards(err){// ~∞%°
    if (err) {
      return SharedErrorHelpers.fatal.failedToLoadSails(err);
    }

    // Get the current global _ value, if any.
    var underscore = global._;

    cliLogger.info('Welcome to the Sails console.');
    cliLogger.info(chalk.grey('( to exit, type ' + '<CTRL>+<C>' + ' )'));
    console.log();

    // Define a custom output stream that will replace global._ after every command.
    // This works around the issue where the Node REPL uses the underscore to hold
    // the result of the last command.
    var outputStream = (function() {
      // Create a new writable stream.
      var writableStream = new stream.Writable();
      // Add the `_write` method to it (can't do this in the constructor b/c that's not supported in older Node versions).
      writableStream._write = function(chunk, encoding, callback) {
        // Ignore the output generated the first time the global _ is set in Node 6+.
        if (chunk.toString('utf8').indexOf('Expression assignment to _ now disabled.') !== -1) {
          return callback();
        }
        // Set the global underscore again (for Node < 6).
        // See code after `REPL.start` for more info.
        if (typeof underscore !== 'undefined') {
          global._ = underscore;
        }
        // Forward the chunk on to stdout.
        process.stdout.write(chunk, encoding, callback);
      };
      // Return the new writable stream.
      return writableStream;
    })();

    // Start a REPL.
    var repl = REPL.start({
      // Set the REPL prompt.
      prompt: 'sails> ',
      // Allow the REPL to use the same global space as the Sails app, giving it access
      // to things like globalized models.
      useGlobal: true,
      // Specify the custom output stream we created above.
      output: outputStream,
      // When an output stream is specified, an input stream must be specified as well
      // or else the REPL crashes.
      input: process.stdin,
      // Set `terminal` to true to allow arrow keys to work correctly,
      // even when we're using a custom output stream.  Otherwise pressing
      // the up arrow just outputs ^[[A instead of accessing history.
      terminal: true
    });

    // Replace the global _ value, if any.  This will deactivate the underscore behavior
    // in the Node REPL for Node 6+, which conflicts with the global _ in Sails apps.
    // Note that in Node 6+ this typically causes the REPL to output "Expression assignment to _ now disabled.",
    // which unfortunately gets put right next to the `sails>` prompt, making for a very confusing
    // introduction to the Sails console.  In the custom output stream we defined above, we filter out
    // that message.
    if (typeof underscore !== 'undefined') {
      global._ = underscore;
    }

    // Now attempt to read the existing REPL history file, if there is one.
    var pathToReplHistoryFile = nodepath.join(sailsApp.config.paths.tmp, '.node_history');
    try {

      // Read the REPL history file, and bind notifier functions that will listen
      // for history-making events, and keep track of them for future generations.
      readReplHistoryAndStartTranscribing(repl, pathToReplHistoryFile);

    }
    catch (e) {

      cliLogger.verbose('Encountered an error attempting to access/interpret a `.node_history` file at `'+pathToReplHistoryFile+'`.');
      cliLogger.verbose('(This session of `sails console` will still work, it just won\'t support REPL history.)');
      cliLogger.verbose('Error details:\n',e);

    }//>-

    // Bind a one-time-use handler that will run when the REPL instance emits its "exit" event.
    repl.once('exit', function(err) {

      // If an error occurred, log it, then terminate the process with an exit code of 1.
      if (err) {
        cliLogger.error(err);
        return process.exit(1);
      }// --•

      // Otherwise, everything is cool.
      // Terminate the process with an exit code of 0.
      return process.exit(0);

    });//</when 'exit' event it emitted by repl instance>

  });//</after lifting or loading Sails app>

};
<commit_msg>Changed the way the app exits with sails console.<commit_after>/**
 * Module dependencies
 */

var nodepath = require('path');
var REPL = require('repl');
var stream = require('stream');
var _ = require('@sailshq/lodash');
var chalk = require('chalk');
var CaptainsLog = require('captains-log');

var rconf = require('../lib/app/configuration/rc')();
var Sails = require('../lib/app');
var SharedErrorHelpers = require('../errors');
var readReplHistoryAndStartTranscribing = require('./private/read-repl-history-and-start-transcribing');

/**
 * `sails console`
 *
 * Enter the interactive console (aka REPL) for the app
 * in our working directory.  This is just like the default
 * Node REPL except that it starts with the Sails app in the
 * current directory lifted, and with console history enabled
 * (i.e. so you can press up arrow to browse and potentially
 *  replay commands from past runs)
 *
 * @stability 3
 * @see http://sailsjs.com/documentation/reference/command-line-interface/sails-console
 * ------------------------------------------------------------------------
 * This lifts the Sails app in the current working directory, then uses
 * the core `repl` package to spin up an interactive console.
 *
 * Note that, if `--dontLift` was set, then `sails.load()` will be used
 * instead. (By default, the `sails console` cmd runs `sails.lift()`.)
 * ------------------------------------------------------------------------
 */

module.exports = function() {

  // Get a temporary logger just for use in `sails console`.
  // > This is so that logging levels are configurable, even when a
  // > Sails app hasn't been loaded yet.
  var cliLogger = CaptainsLog(rconf.log);

  // Now grab our dictionary of configuration overrides to pass in
  // momentarily when we lift (or load) our Sails app.  This is the
  // dictionary of configuration settings built from `.sailsrc` file(s),
  // command-line options, and environment variables.
  // (No need to clone, since, even through we're modifying it below,
  //  it's not being used anywhere else.)
  var configOverrides = rconf;

  // Then tweak this configuration to make sure we always disable
  // the ASCII ship.  It just doesn't look good in the REPL.
  if (!_.isObject(configOverrides.log)) {
    configOverrides.log = {};
  }
  configOverrides.log.noShip = true;

  // Determine whether to use the local or global Sails install.
  var sailsApp = (function _determineAppropriateSailsAppInstance(){

    // Use the app's locally-installed Sails dependency (in `node_modules/sails`),
    // assuming it's extant and valid.
    // > Note that we always assume the current working directory to be the
    // > root directory of the app.
    var appPath = process.cwd();
    var localSailsPath = nodepath.resolve(appPath, 'node_modules/sails');
    if (Sails.isLocalSailsValid(localSailsPath, appPath)) {
      cliLogger.verbose('Using locally-installed Sails.');
      cliLogger.silly('(which is located at `'+localSailsPath+'`)');
      return require(localSailsPath);
    }// --•

    // Otherwise, since no workable locally-installed Sails exists,
    // run the app using the currently running version of Sails.
    // > This is probably always the global install.
    cliLogger.info('No local Sails install detected; using globally-installed Sails.');

    return Sails();

  })();

  console.log();
  if (configOverrides.dontLift) {
    cliLogger.info(chalk.blue('Loading app in interactive mode...'));
    cliLogger.info(chalk.gray('Sails is not listening for requests (since `dontLift` was enabled).'));
    cliLogger.info(chalk.gray('You still have access to your models, helpers, and `sails`.'));
  }
  else {
    cliLogger.info(chalk.blue('Starting app in interactive mode...'));
  }
  console.log();

  // Lift (or load) Sails
  (function _loadOrLift(proceed){

    // If `--dontLift` was set, then use `.load()` instead.
    if (configOverrides.dontLift) {
      sailsApp.load(configOverrides, proceed);
    }
    // Otherwise, go with the default behavior (`.lift()`)
    else {
      sailsApp.lift(configOverrides, proceed);
    }

  })(function afterwards(err){// ~∞%°
    if (err) {
      return SharedErrorHelpers.fatal.failedToLoadSails(err);
    }

    // Get the current global _ value, if any.
    var underscore = global._;

    cliLogger.info('Welcome to the Sails console.');
    cliLogger.info(chalk.grey('( to exit, type ' + '<CTRL>+<C>' + ' )'));
    console.log();

    // Define a custom output stream that will replace global._ after every command.
    // This works around the issue where the Node REPL uses the underscore to hold
    // the result of the last command.
    var outputStream = (function() {
      // Create a new writable stream.
      var writableStream = new stream.Writable();
      // Add the `_write` method to it (can't do this in the constructor b/c that's not supported in older Node versions).
      writableStream._write = function(chunk, encoding, callback) {
        // Ignore the output generated the first time the global _ is set in Node 6+.
        if (chunk.toString('utf8').indexOf('Expression assignment to _ now disabled.') !== -1) {
          return callback();
        }
        // Set the global underscore again (for Node < 6).
        // See code after `REPL.start` for more info.
        if (typeof underscore !== 'undefined') {
          global._ = underscore;
        }
        // Forward the chunk on to stdout.
        process.stdout.write(chunk, encoding, callback);
      };
      // Return the new writable stream.
      return writableStream;
    })();

    // Start a REPL.
    var repl = REPL.start({
      // Set the REPL prompt.
      prompt: 'sails> ',
      // Allow the REPL to use the same global space as the Sails app, giving it access
      // to things like globalized models.
      useGlobal: true,
      // Specify the custom output stream we created above.
      output: outputStream,
      // When an output stream is specified, an input stream must be specified as well
      // or else the REPL crashes.
      input: process.stdin,
      // Set `terminal` to true to allow arrow keys to work correctly,
      // even when we're using a custom output stream.  Otherwise pressing
      // the up arrow just outputs ^[[A instead of accessing history.
      terminal: true
    });

    // Replace the global _ value, if any.  This will deactivate the underscore behavior
    // in the Node REPL for Node 6+, which conflicts with the global _ in Sails apps.
    // Note that in Node 6+ this typically causes the REPL to output "Expression assignment to _ now disabled.",
    // which unfortunately gets put right next to the `sails>` prompt, making for a very confusing
    // introduction to the Sails console.  In the custom output stream we defined above, we filter out
    // that message.
    if (typeof underscore !== 'undefined') {
      global._ = underscore;
    }

    // Now attempt to read the existing REPL history file, if there is one.
    var pathToReplHistoryFile = nodepath.join(sailsApp.config.paths.tmp, '.node_history');
    try {

      // Read the REPL history file, and bind notifier functions that will listen
      // for history-making events, and keep track of them for future generations.
      readReplHistoryAndStartTranscribing(repl, pathToReplHistoryFile);

    }
    catch (e) {

      cliLogger.verbose('Encountered an error attempting to access/interpret a `.node_history` file at `'+pathToReplHistoryFile+'`.');
      cliLogger.verbose('(This session of `sails console` will still work, it just won\'t support REPL history.)');
      cliLogger.verbose('Error details:\n',e);

    }//>-

    // Bind a one-time-use handler that will run when the REPL instance emits its "exit" event.
    repl.once('exit', function(err) {

      // If an error occurred, log it, then terminate the process with an exit code of 1.
      if (err) {
        cliLogger.error(err);
        return process.exit(1);
      }// --•

      // Otherwise, everything is cool.
      // Call the core 'lower' function and terminate the process with an exit code of 0.
      sailsApp.lower(function () {
        return process.exit(0);
      });

    });//</when 'exit' event it emitted by repl instance>

  });//</after lifting or loading Sails app>

};
<|endoftext|>


<commit_before>#!/usr/bin/env node
var assert = require('assert');

var async = require('async');
var express = require('express');
var request = require('request');
var sugar = require('object-sugar');

var rest = require('../lib/rest-sugar');
var models = require('./models');

main();

function main() {
    var host = 'http://localhost';
    var port = 3000;
    var prefix = '/api/';
    var resource = host + ':' + port + prefix + 'authors';
    var app = express();

    app.configure(function() {
        app.use(express.methodOverride()); // handles PUT
        app.use(express.bodyParser()); // handles POST
        app.use(app.router);
    });

    rest.init(app, prefix, {
        authors: models.Author
    }, sugar, function(err, ok) {
        // TODO: perhaps treat this as a middleware instead and provide "next"?
        return function(req, res) {
            ok(req, res);
        };
    }, function(req, res, body) {

    });

    start();
    app.listen(port, function(err) {
        if(err) return console.error(err);

        async.series(setup([
            getResource(resource),
            getResourceViaId(resource),
            createResource(resource),
            createResourceViaGet(resource),
            createResourceViaId(resource),
            updateResource(resource),
            updateResourceViaGet(resource),
            updateResourceViaId(resource),
            removeResource(resource),
            removeResourceViaGet(resource),
            removeResourceViaId(resource)
        ], removeData), finish);
    });
}

function removeData(t) {
    return function(cb) {
        async.series([
            removeAuthors
        ], t.bind(undefined, cb));
    };
}

function removeAuthors(cb) {
    sugar.removeAll(models.Author, cb);
}

function setup(tests, fn) {
    return tests.map(function(t) {
        return fn(t);
    });
}

function getResource(r) {
    return function(cb) {
        request.get({url: r, json: true}, function(err, d, body) {
            if(err) return console.error(err);

            assert.equal(body.length, 0);

            cb(err, d, body);
        });
    };
}

function getResourceViaId(r) {
    return function(cb) {
        createResource(r)(function(err, d, body) {
            request.get({url: r + '/' + body._id, json: true}, function(err, d, b) {
                if(err) return console.error(err);

                assert.equal(body._id, b._id);
                assert.equal(body.name, b.name);

                cb(err, d, body);
            });
        });
    };
}

function createResource(r) {
    return function(cb) {
        var name = 'Joe';

        request.post({url: r, json: {name: name}}, function(err, d, body) {
            if(err) return console.error(err);

            assert.equal(body.name, name);

            cb(err, d, body);
        });
    };
}

function createResourceViaGet(r) {
    return function(cb) {
        var name = 'Jack';

        request.get({url: r, qs: {name: name, method: 'post'}, json: true}, function(err, d, body) {
            if(err) return console.error(err);

            assert.equal(body.name, name);

            cb(err, d, body);
        });
    };
}

function createResourceViaId(r) {
    return function(cb) {
        createResource(r)(function(err, d, body) {
            request.post({url: r + '/' + body._id}, function(err, d, body) {
                if(err) return console.error(err);

                assert.equal(d.statusCode, 403);

                cb(err, d, body);
            });
        });
    };
}

function updateResource(r) {
    return function(cb) {
        createResource(r)(function(err, d, body) {
            var id = body._id;
            var name = body.name + body.name;

            request.put({url: r, json: {_id: id, name: name}}, function(err, d, body) {
                if(err) return console.error(err);

                assert.equal(id, body._id);
                assert.equal(name, body.name);

                cb(err, d, body);
            });
        });
    };
}

function updateResourceViaGet(r) {
    return function(cb) {
        // TODO
        cb();
    };
}

function updateResourceViaId(r) {
    return function(cb) {
        // TODO
        cb();
    };
}

function removeResource(r) {
    return function(cb) {
        // TODO
        cb();
    };
}

function removeResourceViaGet(r) {
    return function(cb) {
        // TODO
        cb();
    };
}

function removeResourceViaId(r) {
    return function(cb) {
        // TODO
        cb();
    };
}

function start() {
    console.log('Running tests!');
}

function finish() {
    console.log('Tests finished!');
    process.exit();
}
<commit_msg>Test updating resource via GET<commit_after>#!/usr/bin/env node
var assert = require('assert');

var async = require('async');
var express = require('express');
var request = require('request');
var sugar = require('object-sugar');

var rest = require('../lib/rest-sugar');
var models = require('./models');

main();

function main() {
    var host = 'http://localhost';
    var port = 3000;
    var prefix = '/api/';
    var resource = host + ':' + port + prefix + 'authors';
    var app = express();

    app.configure(function() {
        app.use(express.methodOverride()); // handles PUT
        app.use(express.bodyParser()); // handles POST
        app.use(app.router);
    });

    rest.init(app, prefix, {
        authors: models.Author
    }, sugar, function(err, ok) {
        // TODO: perhaps treat this as a middleware instead and provide "next"?
        return function(req, res) {
            ok(req, res);
        };
    }, function(req, res, body) {

    });

    start();
    app.listen(port, function(err) {
        if(err) return console.error(err);

        async.series(setup([
            getResource(resource),
            getResourceViaId(resource),
            createResource(resource),
            createResourceViaGet(resource),
            createResourceViaId(resource),
            updateResource(resource),
            updateResourceViaGet(resource),
            updateResourceViaId(resource),
            removeResource(resource),
            removeResourceViaGet(resource),
            removeResourceViaId(resource)
        ], removeData), finish);
    });
}

function removeData(t) {
    return function(cb) {
        async.series([
            removeAuthors
        ], t.bind(undefined, cb));
    };
}

function removeAuthors(cb) {
    sugar.removeAll(models.Author, cb);
}

function setup(tests, fn) {
    return tests.map(function(t) {
        return fn(t);
    });
}

function getResource(r) {
    return function(cb) {
        request.get({url: r, json: true}, function(err, d, body) {
            if(err) return console.error(err);

            assert.equal(body.length, 0);

            cb(err, d, body);
        });
    };
}

function getResourceViaId(r) {
    return function(cb) {
        createResource(r)(function(err, d, body) {
            request.get({url: r + '/' + body._id, json: true}, function(err, d, b) {
                if(err) return console.error(err);

                assert.equal(body._id, b._id);
                assert.equal(body.name, b.name);

                cb(err, d, body);
            });
        });
    };
}

function createResource(r) {
    return function(cb) {
        var name = 'Joe';

        request.post({url: r, json: {name: name}}, function(err, d, body) {
            if(err) return console.error(err);

            assert.equal(body.name, name);

            cb(err, d, body);
        });
    };
}

function createResourceViaGet(r) {
    return function(cb) {
        var name = 'Jack';

        request.get({url: r, qs: {name: name, method: 'post'}, json: true}, function(err, d, body) {
            if(err) return console.error(err);

            assert.equal(body.name, name);

            cb(err, d, body);
        });
    };
}

function createResourceViaId(r) {
    return function(cb) {
        createResource(r)(function(err, d, body) {
            request.post({url: r + '/' + body._id}, function(err, d, body) {
                if(err) return console.error(err);

                assert.equal(d.statusCode, 403);

                cb(err, d, body);
            });
        });
    };
}

function updateResource(r) {
    return function(cb) {
        createResource(r)(function(err, d, body) {
            var id = body._id;
            var name = body.name + body.name;

            request.put({url: r, json: {_id: id, name: name}}, function(err, d, body) {
                if(err) return console.error(err);

                assert.equal(id, body._id);
                assert.equal(name, body.name);

                cb(err, d, body);
            });
        });
    };
}

function updateResourceViaGet(r) {
    return function(cb) {
        createResource(r)(function(err, d, body) {
            var id = body._id;
            var name = body.name + body.name;

            request.get({url: r + '/' + id, qs: {name: name, method: 'put'}, json: true}, function(err, d, body) {
                if(err) return console.error(err);

                assert.equal(id, body._id);
                assert.equal(name, body.name);

                cb(err, d, body);
            });
        });
    };
}

function updateResourceViaId(r) {
    return function(cb) {
        // TODO
        cb();
    };
}

function removeResource(r) {
    return function(cb) {
        // TODO
        cb();
    };
}

function removeResourceViaGet(r) {
    return function(cb) {
        // TODO
        cb();
    };
}

function removeResourceViaId(r) {
    return function(cb) {
        // TODO
        cb();
    };
}

function start() {
    console.log('Running tests!');
}

function finish() {
    console.log('Tests finished!');
    process.exit();
}
<|endoftext|>