<commit_before>/*jshint node: true, -W106 */
'use strict';

/*
* Name : mapChartFlowSpec.js
* Module : UnitTest
* Location : /test/businessTier/flow
*
* History :
*
* Version   Date         Programmer         Description
* =========================================================
* 0.0.1     2015-06-02   Matteo Furlan    Initial code
* =========================================================
*/

var LineChartFlow = require('../../../lib/businessTier/flow/lineChartFlow.js');
var assert = require('assert');

var socketMock=function(){
    this.p1=null;
    this.p2=null;
    this._namespace='flow1';
    this.sendMessage=function(p1, p2){
        this.p1=p1;
        this.p2=p2;
    };
};

describe('LineChartFlow', function() {

    it('returns null when there are no params', function() {
        assert.strictEqual((new LineChartFlow()).hasOwnProperty('_dataLineChartFlow'), false);
    });

    it('returns null when there is no valid graphsocket in params', function() {
        assert.strictEqual((new LineChartFlow(2, 3)).hasOwnProperty('_dataLineChartFlow'), false);
    });

    it('returns null when params are not valid', function() {
        assert.strictEqual((new LineChartFlow(2, {_namespace: 2})).hasOwnProperty('_dataLineChartFlow'), false);
    });

    it('calls the parent constructor with the params specified', function() {
        var flow1=new LineChartFlow({ID: 'flow1'},new socketMock());
        assert.strictEqual(flow1._dataLineChartFlow._ID, 'flow1');
        assert.strictEqual(flow1._graphSocket._namespace, 'flow1');
    });

    describe('#addRecord', function() {
        it('returns 123 if record is invalid', function() {
            var flow1=new LineChartFlow({ID: 'flow1'},new socketMock());
            assert.strictEqual(flow1.addRecord(), 123);
        });
        it('returns valid norrisRecordID if record is valid', function() {
            var flow1=new LineChartFlow({ID: 'flow1'},new socketMock());
            assert.strictEqual(flow1.addRecord({'tempo': 1, 'temperatura': 25}).indexOf('flow1'), 0);
        });
    });

    describe('#updateRecord', function() {
        it('returns 123 if record is invalid', function() {
            var flow1=new LineChartFlow({ID: 'flow1'},new socketMock());
            flow1.addRecord({'tempo': 1, 'temperatura': 25});
            assert.strictEqual(flow1.updateRecord(), 121);
        });
        it('returns 122 if no ID in records', function() {
            var flow1=new LineChartFlow({ID: 'flow1'},new socketMock());
            var ID=flow1.addRecord({'tempo': 1, 'temperatura': 25});
            assert.strictEqual(flow1.updateRecord(ID+'32442',{'tempo': 4, 'temperatura': 33}), 122);
        });
        it('returns 122 if invalid ID', function() {
            var flow1=new LineChartFlow({ID: 'flow1'},new socketMock());
            var ID=flow1.addRecord({'tempo': 1, 'temperatura': 25});
            assert.strictEqual(flow1.updateRecord('sad'+ID,{'tempo': 4, 'temperatura': 33}), 122);
        });
        it('returns true with correct update', function() {
            var mock=new socketMock();
            var flow1=new LineChartFlow({
                    ID: 'flow1',
                    filters: 'temperature>3',
                    xKey: 'a',
                    yKey: 'b'
                }, mock);
            var ID=flow1.addRecord({temperature: 5, a:1, b:2});
            flow1.addRecord({temperature: 6, a:1, b:2});
            flow1.updateRecord(ID, {temperature: 0});
            assert.strictEqual(mock.p1, 'updateFlowData');
            assert.deepEqual(mock.p2, {
                action: 'deleteRecord',
                ID: 'flow1',
                norrisRecordID: ID
            });
            flow1.addRecord({temperature: 5, a:1, b:2});
            assert.strictEqual(mock.p1, 'updateFlowData');
            assert.deepEqual(mock.p2, {
                action: 'insertRecords',
                ID: 'flow1',
                records: [{
                    norrisRecordID: ID,
                    value: [1,2]
                }]
            });
            flow1.addRecord({temperature: 6, a:1, b:2});
            assert.strictEqual(mock.p1, 'updateFlowData');
            assert.deepEqual(mock.p2, {
                action: 'updateRecord',
                ID: 'flow1',
                norrisRecordID: ID,
                value: [1,2]
            });
        });
    });

    describe('#getReplaceDataJSON', function() {
        var flow1=new LineChartFlow({ID: 'flow1', name: 'grafico tempo-temperatura',xKey: 'tempo',yKey: 'temperatura'},new socketMock());
        var ID1=flow1.addRecord({'tempo': 4, 'temperatura': 4});
        var ID2=flow1.addRecord({'tempo': 9, 'temperatura': 23});
        var ID3=flow1.addRecord({'tempo': 6, 'temperatura': 7});
        assert.deepEqual(flow1.getReplaceDataJSON(),{'action':'replaceData','ID':'flow1','records':[{'norrisRecordID':ID1,'value':[4,4]},{'norrisRecordID':ID2,'value':[9,23]},{'norrisRecordID':ID3,'value':[6,7]}]});
    });

    describe('#updateProperties', function() {
        var flow1=new LineChartFlow({ID: 'flow1'},new socketMock());
        flow1.updateProperties({name: 'grafico tempo-temperatura',xKey: 'tempo',yKey: 'temperatura',filters: 'temperature>3',});
        assert.strictEqual(flow1._dataLineChartFlow._xKey,'tempo');
        assert.strictEqual(flow1._dataLineChartFlow._yKey,'temperatura');
        assert.strictEqual(flow1._dataLineChartFlow._name,'grafico tempo-temperatura');
    });
});<commit_msg>fix test<commit_after>/*jshint node: true, -W106 */
'use strict';

/*
* Name : mapChartFlowSpec.js
* Module : UnitTest
* Location : /test/businessTier/flow
*
* History :
*
* Version   Date         Programmer         Description
* =========================================================
* 0.0.1     2015-06-02   Matteo Furlan    Initial code
* =========================================================
*/

var LineChartFlow = require('../../../lib/businessTier/flow/lineChartFlow.js');
var assert = require('assert');

var socketMock=function(){
    this.p1=null;
    this.p2=null;
    this._namespace='flow1';
    this.sendMessage=function(p1, p2){
        this.p1=p1;
        this.p2=p2;
    };
};

describe('LineChartFlow', function() {

    it('returns null when there are no params', function() {
        assert.strictEqual((new LineChartFlow()).hasOwnProperty('_dataLineChartFlow'), false);
    });

    it('returns null when there is no valid graphsocket in params', function() {
        assert.strictEqual((new LineChartFlow(2, 3)).hasOwnProperty('_dataLineChartFlow'), false);
    });

    it('returns null when params are not valid', function() {
        assert.strictEqual((new LineChartFlow(2, {_namespace: 2})).hasOwnProperty('_dataLineChartFlow'), false);
    });

    it('calls the parent constructor with the params specified', function() {
        var flow1=new LineChartFlow({ID: 'flow1'},new socketMock());
        assert.strictEqual(flow1._dataLineChartFlow._ID, 'flow1');
        assert.strictEqual(flow1._graphSocket._namespace, 'flow1');
    });

    describe('#addRecord', function() {
        it('returns 123 if record is invalid', function() {
            var flow1=new LineChartFlow({ID: 'flow1'},new socketMock());
            assert.strictEqual(flow1.addRecord(), 123);
        });
        it('returns valid norrisRecordID if record is valid', function() {
            var flow1=new LineChartFlow({ID: 'flow1'},new socketMock());
            assert.strictEqual(flow1.addRecord({'tempo': 1, 'temperatura': 25}).indexOf('flow1'), 0);
        });
    });

    describe('#updateRecord', function() {
        it('returns 123 if record is invalid', function() {
            var flow1=new LineChartFlow({ID: 'flow1'},new socketMock());
            flow1.addRecord({'tempo': 1, 'temperatura': 25});
            assert.strictEqual(flow1.updateRecord(), 121);
        });
        it('returns 122 if no ID in records', function() {
            var flow1=new LineChartFlow({ID: 'flow1'},new socketMock());
            var ID=flow1.addRecord({'tempo': 1, 'temperatura': 25});
            assert.strictEqual(flow1.updateRecord(ID+'32442',{'tempo': 4, 'temperatura': 33}), 122);
        });
        it('returns 122 if invalid ID', function() {
            var flow1=new LineChartFlow({ID: 'flow1'},new socketMock());
            var ID=flow1.addRecord({'tempo': 1, 'temperatura': 25});
            assert.strictEqual(flow1.updateRecord('sad'+ID,{'tempo': 4, 'temperatura': 33}), 122);
        });
        it('returns true with correct update', function() {
            var mock=new socketMock();
            var flow1=new LineChartFlow({
                    ID: 'flow1',
                    filters: 'temperature>3',
                    xKey: 'a',
                    yKey: 'b'
                }, mock);
            var ID=flow1.addRecord({temperature: 5, a:1, b:2});
            flow1.addRecord({temperature: 6, a:1, b:2});
            flow1.updateRecord(ID, {temperature: 0});
            assert.strictEqual(mock.p1, 'updateFlowData');
            assert.deepEqual(mock.p2, {
                action: 'deleteRecord',
                ID: 'flow1',
                norrisRecordID: ID
            });
            flow1.addRecord({temperature: 5, a:1, b:2});
            assert.strictEqual(mock.p1, 'updateFlowData');
            assert.deepEqual(mock.p2, {
                action: 'insertRecords',
                ID: 'flow1',
                records: [{
                    norrisRecordID: ID,
                    value: [1,2]
                }]
            });
            flow1.addRecord({temperature: 6, a:1, b:2});
            assert.strictEqual(mock.p1, 'updateFlowData');
            assert.deepEqual(mock.p2, {
                action: 'updateRecord',
                ID: 'flow1',
                norrisRecordID: ID,
                value: [1,2]
            });
        });
    });

    describe('#getReplaceDataJSON', function() {
        it('returns correct JSON', function() {
            var flow1=new LineChartFlow({ID: 'flow1', name: 'grafico tempo-temperatura',xKey: 'tempo',yKey: 'temperatura'},new socketMock());
            var ID1=flow1.addRecord({'tempo': 4, 'temperatura': 4});
            var ID2=flow1.addRecord({'tempo': 9, 'temperatura': 23});
            var ID3=flow1.addRecord({'tempo': 6, 'temperatura': 7});
            assert.deepEqual(flow1.getReplaceDataJSON(),{'action':'replaceData','ID':'flow1','records':[{'norrisRecordID':ID1,'value':[4,4]},{'norrisRecordID':ID2,'value':[9,23]},{'norrisRecordID':ID3,'value':[6,7]}]});
        });
    });

    describe('#updateProperties', function() {
        it('update correct properties', function() {
            var flow1=new LineChartFlow({ID: 'flow1'},new socketMock());
            flow1.updateProperties({name: 'grafico tempo-temperatura',xKey: 'tempo',yKey: 'temperatura',filters: 'temperature>3',});
            assert.strictEqual(flow1._dataLineChartFlow._xKey,'tempo');
            assert.strictEqual(flow1._dataLineChartFlow._yKey,'temperatura');
            assert.strictEqual(flow1._dataLineChartFlow._name,'grafico tempo-temperatura');
        });
    });
});<|endoftext|>


<commit_before>var bar;
;;
/* lumbar module map */
App.moduleMap({"modules":{"base":{"css":{"href":"base.css"},"js":"base.js"},"home":{"js":"home.js"}},"routes":{"home":"home"}});
<commit_msg>Fix tests<commit_after>var bar;

;;
/* lumbar module map */
App.moduleMap({"modules":{"base":{"css":{"href":"base.css"},"js":"base.js"},"home":{"js":"home.js"}},"routes":{"home":"home"}});
<|endoftext|>


<commit_before>var falcor = require("./../../../lib/");
var Model = falcor.Model;
var noOp = function() {};
var expect = require('chai').expect;
var sinon = require('sinon');
var LocalDataSource = require('./../../data/LocalDataSource');
var Cache = require('./../../data/Cache');

describe('DataSource.', function() {
    it('should validate args are sent to the dataSource collapsed.', function(done) {
        var onSet = sinon.spy(function(source, tmpGraph, jsonGraphFromSet) {
            return jsonGraphFromSet;
        });
        var dataSource = new LocalDataSource(Cache(), {
            onSet: onSet
        });
        var model = new Model({
            source: dataSource
        });
        model.
            set({
                json: {
                    videos: {
                        1234: {
                            rating: 5
                        },
                        444: {
                            rating: 3
                        }
                    }
                }
            }).
            doAction(noOp, noOp, function() {
                expect(onSet.calledOnce).to.be.ok;

                var cleaned = onSet.getCall(0).args[2];
                cleaned.paths[0][1] = cleaned.paths[0][1].concat();
                expect(cleaned).to.deep.equals({
                    jsonGraph: {
                        videos: {
                            1234: {
                                rating: 5
                            },
                            444: {
                                rating: 3
                            }
                        }
                    },
                    paths: [
                        ['videos', [444, 1234], 'rating']
                    ]
                });
            }).
            subscribe(noOp, done, done);
    });

    it('should send off undefined on a set to the server.', function(done) {
        var onSet = sinon.spy(function(source, tmpGraph, jsonGraphFromSet) {
            return jsonGraphFromSet;
        });
        var dataSource = new LocalDataSource(Cache(), {
            onSet: onSet
        });
        var model = new Model({
            source: dataSource
        });
        model.
            set({
                json: {
                    videos: {
                        1234: {
                            another_prop: undefined
                        }
                    }
                }
            }).
            doAction(noOp, noOp, function() {
                expect(onSet.calledOnce).to.be.ok;

                var cleaned = onSet.getCall(0).args[2];
                expect(cleaned).to.deep.equals({
                    jsonGraph: {
                        videos: {
                            1234: {
                                another_prop: {
                                    $type: 'atom'
                                }
                            }
                        }
                    },
                    paths: [
                        ['videos', 1234, 'another_prop']
                    ]
                });
            }).
            subscribe(noOp, done, done);
    });
});
<commit_msg>added the empty string test.<commit_after>var falcor = require("./../../../lib/");
var Model = falcor.Model;
var noOp = function() {};
var expect = require('chai').expect;
var sinon = require('sinon');
var LocalDataSource = require('./../../data/LocalDataSource');
var Cache = require('./../../data/Cache');

describe('DataSource.', function() {
    it('should validate args are sent to the dataSource collapsed.', function(done) {
        var onSet = sinon.spy(function(source, tmpGraph, jsonGraphFromSet) {
            return jsonGraphFromSet;
        });
        var dataSource = new LocalDataSource(Cache(), {
            onSet: onSet
        });
        var model = new Model({
            source: dataSource
        });
        model.
            set({
                json: {
                    videos: {
                        1234: {
                            rating: 5
                        },
                        444: {
                            rating: 3
                        }
                    }
                }
            }).
            doAction(noOp, noOp, function() {
                expect(onSet.calledOnce).to.be.ok;

                var cleaned = onSet.getCall(0).args[2];
                cleaned.paths[0][1] = cleaned.paths[0][1].concat();
                expect(cleaned).to.deep.equals({
                    jsonGraph: {
                        videos: {
                            1234: {
                                rating: 5
                            },
                            444: {
                                rating: 3
                            }
                        }
                    },
                    paths: [
                        ['videos', [444, 1234], 'rating']
                    ]
                });
            }).
            subscribe(noOp, done, done);
    });

    it('should send off an empty string on a set to the server.', function(done) {
        var onSet = sinon.spy(function(source, tmpGraph, jsonGraphFromSet) {
            return jsonGraphFromSet;
        });
        var dataSource = new LocalDataSource(Cache(), {
            onSet: onSet
        });
        var model = new Model({
            source: dataSource
        });
        model.
            setValue('videos[1234].another_prop', '').
            doAction(noOp, noOp, function() {
                expect(onSet.calledOnce).to.be.ok;

                var cleaned = onSet.getCall(0).args[2];
                expect(cleaned).to.deep.equals({
                    jsonGraph: {
                        videos: {
                            1234: {
                                another_prop: ''
                            }
                        }
                    },
                    paths: [
                        ['videos', 1234, 'another_prop']
                    ]
                });
            }).
            subscribe(noOp, done, done);
    });

    it('should send off undefined on a set to the server.', function(done) {
        var onSet = sinon.spy(function(source, tmpGraph, jsonGraphFromSet) {
            return jsonGraphFromSet;
        });
        var dataSource = new LocalDataSource(Cache(), {
            onSet: onSet
        });
        var model = new Model({
            source: dataSource
        });
        model.
            set({
                json: {
                    videos: {
                        1234: {
                            another_prop: undefined
                        }
                    }
                }
            }).
            doAction(noOp, noOp, function() {
                expect(onSet.calledOnce).to.be.ok;

                var cleaned = onSet.getCall(0).args[2];
                expect(cleaned).to.deep.equals({
                    jsonGraph: {
                        videos: {
                            1234: {
                                another_prop: {
                                    $type: 'atom'
                                }
                            }
                        }
                    },
                    paths: [
                        ['videos', 1234, 'another_prop']
                    ]
                });
            }).
            subscribe(noOp, done, done);
    });
});
<|endoftext|>


<commit_before>var fs = require('fs'),

    _ = require('lodash'),
    parseXml = require('xml2js').parseString;

/* global beforeEach, afterEach, describe, it, expect, newman */
describe('JUnit reporter', function () {
    var outFile = 'out/newman-report.xml';

    beforeEach(function (done) {
        fs.stat('out', function (err) {
            if (err) {
                return fs.mkdir('out', done);
            }

            done();
        });
    });

    afterEach(function (done) {
        fs.stat(outFile, function (err) {
            if (err) {
                return done();
            }

            fs.unlink(outFile, done);
        });
    });

    it('should correctly generate the JUnit report for a successful run', function (done) {
        newman.run({
            collection: 'test/fixtures/run/single-get-request.json',
            reporters: ['junit'],
            reporter: { junit: { export: outFile } }
        }, function (err) {
            if (err) { return done(err); }

            fs.readFile(outFile, function (err, data) {
                expect(err).to.not.be.ok();

                parseXml(data, function (error, result) {
                    expect(error).to.not.be.ok();

                    var suite = _.get(result.testsuites, 'testsuite.0');
                    expect(suite).to.not.be.empty();
                    expect(suite.$).to.not.be.empty();
                    expect(suite.testcase).to.not.be.empty();

                    expect(suite.$).to.have.property('tests', '1');
                    expect(suite.$).to.have.property('failures', '0');
                    expect(suite.$).to.have.property('errors', '0');

                    done();
                });
            });
        });
    });

    it('should correctly generate the JUnit report for a failed run', function (done) {
        newman.run({
            collection: 'test/fixtures/run/single-request-failing.json',
            reporters: ['junit'],
            reporter: { junit: { export: outFile } }
        }, function (err, summary) {
            expect(err).to.be(null);
            expect(summary.run.failures).to.have.length(1);
            fs.readFile(outFile, function (err, data) {
                expect(err).to.not.be.ok();

                parseXml(data, function (error, result) {
                    expect(error).to.not.be.ok();

                    var testcase,
                        suite = _.get(result.testsuites, 'testsuite.0');

                    expect(suite).to.not.be.empty();
                    expect(suite.$).to.not.be.empty();
                    expect(suite.testcase).to.not.be.empty();

                    expect(suite.$).to.have.property('tests', '1');
                    expect(suite.$).to.have.property('failures', '1');
                    expect(suite.$).to.have.property('errors', '0');

                    testcase = suite.testcase[0];
                    expect(testcase).to.not.be.empty();

                    expect(testcase.$).to.have.property('classname', 'JUnitXmlReporter.constructor');
                    expect(testcase.failure).to.not.be.empty();
                    expect(testcase.failure[0]._).to.not.be.empty();
                    expect(testcase.failure[0].$).to.have.property('type', 'AssertionFailure');

                    expect(testcase.failure).to.not.be.empty();
                    done();
                });
            });
        });
    });

    it('should correctly produce the JUnit report for a run with AssertionError/TypeError', function (done) {
        newman.run({
            collection: 'test/fixtures/run/newman-report-test.json',
            reporters: ['junit'],
            reporter: { junit: { export: outFile } }
        }, function (err, summary) {
            expect(err).to.be(null);
            expect(summary.run.failures).to.have.length(2);
            fs.readFile(outFile, function (err, data) {
                expect(err).to.not.be.ok();

                parseXml(data, function (error, result) {
                    expect(error).to.not.be.ok();

                    var testcase,
                        suite = _.get(result.testsuites, 'testsuite.0');

                    expect(suite).to.not.be.empty();
                    expect(suite.$).to.not.be.empty();
                    expect(suite.testcase).to.not.be.empty();

                    expect(suite.$).to.have.property('tests', '2');
                    expect(suite.$).to.have.property('failures', '1');
                    expect(suite.$).to.have.property('errors', '1');

                    testcase = suite.testcase[0];
                    expect(testcase).to.not.be.empty();

                    expect(testcase.$).to.have.property('classname', 'JUnitXmlReporter.constructor');
                    expect(testcase.failure).to.not.be.empty();
                    expect(testcase.failure[0]._).to.not.be.empty();
                    expect(testcase.failure[0].$).to.have.property('type', 'AssertionFailure');

                    done();
                });
            });
        });
    });
});
<commit_msg>Updated library tests for JUnit reporter time precision bugfix :white_check_mark:<commit_after>var fs = require('fs'),

    _ = require('lodash'),
    parseXml = require('xml2js').parseString;

/* global beforeEach, afterEach, describe, it, expect, newman */
describe('JUnit reporter', function () {
    var outFile = 'out/newman-report.xml';

    beforeEach(function (done) {
        fs.stat('out', function (err) {
            if (err) {
                return fs.mkdir('out', done);
            }

            done();
        });
    });

    afterEach(function (done) {
        fs.stat(outFile, function (err) {
            if (err) {
                return done();
            }

            fs.unlink(outFile, done);
        });
    });

    it('should correctly generate the JUnit report for a successful run', function (done) {
        newman.run({
            collection: 'test/fixtures/run/single-get-request.json',
            reporters: ['junit'],
            reporter: { junit: { export: outFile } }
        }, function (err) {
            if (err) { return done(err); }

            fs.readFile(outFile, function (err, data) {
                expect(err).to.not.be.ok();

                parseXml(data, function (error, result) {
                    expect(error).to.not.be.ok();

                    var suite = _.get(result.testsuites, 'testsuite.0');

                    expect(result.testsuites.$).to.not.be.empty();
                    expect(result.testsuites.$.time).to.match(/^\d+\.\d{3}$/);

                    expect(suite).to.not.be.empty();
                    expect(suite.$).to.not.be.empty();
                    expect(suite.$.time).to.match(/^\d+\.\d{3}$/);
                    expect(suite.testcase).to.not.be.empty();

                    expect(suite.$).to.have.property('tests', '1');
                    expect(suite.$).to.have.property('failures', '0');
                    expect(suite.$).to.have.property('errors', '0');

                    done();
                });
            });
        });
    });

    it('should correctly generate the JUnit report for a failed run', function (done) {
        newman.run({
            collection: 'test/fixtures/run/single-request-failing.json',
            reporters: ['junit'],
            reporter: { junit: { export: outFile } }
        }, function (err, summary) {
            expect(err).to.be(null);
            expect(summary.run.failures).to.have.length(1);
            fs.readFile(outFile, function (err, data) {
                expect(err).to.not.be.ok();

                parseXml(data, function (error, result) {
                    expect(error).to.not.be.ok();

                    var testcase,
                        suite = _.get(result.testsuites, 'testsuite.0');

                    expect(result.testsuites.$).to.not.be.empty();
                    expect(result.testsuites.$.time).to.match(/^\d+\.\d{3}$/);

                    expect(suite).to.not.be.empty();
                    expect(suite.$).to.not.be.empty();
                    expect(suite.$.time).to.match(/^\d+\.\d{3}$/);
                    expect(suite.testcase).to.not.be.empty();

                    expect(suite.$).to.have.property('tests', '1');
                    expect(suite.$).to.have.property('failures', '1');
                    expect(suite.$).to.have.property('errors', '0');

                    testcase = suite.testcase[0];
                    expect(testcase).to.not.be.empty();

                    expect(testcase.$).to.have.property('classname', 'JUnitXmlReporter.constructor');
                    expect(testcase.$.time).to.match(/^\d+\.\d{3}$/);
                    expect(testcase.failure).to.not.be.empty();
                    expect(testcase.failure[0]._).to.not.be.empty();
                    expect(testcase.failure[0].$).to.have.property('type', 'AssertionFailure');

                    expect(testcase.failure).to.not.be.empty();
                    done();
                });
            });
        });
    });

    it('should correctly produce the JUnit report for a run with AssertionError/TypeError', function (done) {
        newman.run({
            collection: 'test/fixtures/run/newman-report-test.json',
            reporters: ['junit'],
            reporter: { junit: { export: outFile } }
        }, function (err, summary) {
            expect(err).to.be(null);
            expect(summary.run.failures).to.have.length(2);
            fs.readFile(outFile, function (err, data) {
                expect(err).to.not.be.ok();

                parseXml(data, function (error, result) {
                    expect(error).to.not.be.ok();

                    var testcase,
                        suite = _.get(result.testsuites, 'testsuite.0');

                    expect(result.testsuites.$).to.not.be.empty();
                    expect(result.testsuites.$.time).to.match(/^\d+\.\d{3}$/);

                    expect(suite).to.not.be.empty();
                    expect(suite.$).to.not.be.empty();
                    expect(suite.$.time).to.match(/^\d+\.\d{3}$/);
                    expect(suite.testcase).to.not.be.empty();

                    expect(suite.$).to.have.property('tests', '2');
                    expect(suite.$).to.have.property('failures', '1');
                    expect(suite.$).to.have.property('errors', '1');

                    testcase = suite.testcase[0];
                    expect(testcase).to.not.be.empty();

                    expect(testcase.$).to.have.property('classname', 'JUnitXmlReporter.constructor');
                    expect(testcase.$.time).to.match(/^\d+\.\d{3}$/);
                    expect(testcase.failure).to.not.be.empty();
                    expect(testcase.failure[0]._).to.not.be.empty();
                    expect(testcase.failure[0].$).to.have.property('type', 'AssertionFailure');

                    done();
                });
            });
        });
    });
});
<|endoftext|>


<commit_before>import Vue from 'vue'

describe('Global API: mixin', () => {
  let options
  beforeEach(() => { options = Vue.options })
  afterEach(() => { Vue.options = options })

  it('should work', () => {
    const spy = jasmine.createSpy('global mixin')
    Vue.mixin({
      created () {
        spy(this.$options.myOption)
      }
    })
    new Vue({
      myOption: 'hello'
    })
    expect(spy).toHaveBeenCalledWith('hello')
  })

  it('should work for constructors created before mixin is applied', () => {
    const calls = []
    const Test = Vue.extend({
      init () {
        calls.push(this.$options.myOption + ' local')
      }
    })
    Vue.mixin({
      init () {
        calls.push(this.$options.myOption + ' global')
      }
    })
    new Test({
      myOption: 'hello'
    })
    expect(calls).toEqual(['hello global', 'hello local'])
  })
})
<commit_msg>coverage for new global mixin strategy<commit_after>import Vue from 'vue'

describe('Global API: mixin', () => {
  let options
  beforeEach(() => { options = Vue.options })
  afterEach(() => { Vue.options = options })

  it('should work', () => {
    const spy = jasmine.createSpy('global mixin')
    Vue.mixin({
      created () {
        spy(this.$options.myOption)
      }
    })
    new Vue({
      myOption: 'hello'
    })
    expect(spy).toHaveBeenCalledWith('hello')
  })

  it('should work for constructors created before mixin is applied', () => {
    const calls = []
    const Test = Vue.extend({
      name: 'test',
      init () {
        calls.push(this.$options.myOption + ' local')
      }
    })
    Vue.mixin({
      init () {
        calls.push(this.$options.myOption + ' global')
      }
    })
    expect(Test.options.name).toBe('test')
    new Test({
      myOption: 'hello'
    })
    expect(calls).toEqual(['hello global', 'hello local'])
  })
})
<|endoftext|>


<commit_before>/**
 * public api for cartodb
 */

(function() {

  function _Promise() {

  }
  _.extend(_Promise.prototype,  Backbone.Events, {
    done: function(fn) {
      return this.bind('done', fn);
    },
    error: function(fn) {
      return this.bind('error', fn);
    }
  });

  cdb._Promise = _Promise;

  var _requestCache = {};

  /**
   * compose cartodb url
   */
  function cartodbUrl(opts) {
    var host = opts.host || 'cartodb.com';
    var protocol = opts.protocol || 'https';
    return protocol + '://' + opts.user + '.' + host + '/api/v1/viz/' + opts.table + '/viz.json';
  }

  /**
   * given layer params fetchs the layer json
   */
  function _getLayerJson(layer, callback) {
    var url = null;
    if(layer.layers !== undefined || ((layer.kind || layer.type) !== undefined)) {
      // layer object contains the layer data
      _.defer(function() { callback(layer); });
      return;
    } else if(layer.table !== undefined && layer.user !== undefined) {
      // layer object points to cartodbjson
      url = cartodbUrl(layer);
    } else {
      // fetch from url
      url = layer;
    }
    if(url) {
      cdb.core.Loader.get(url, callback);
    } else {
      _.defer(function() { callback(null); });
    }
  }

  /**
   * create a layer for the specified map
   *
   * @param map should be a L.Map object, or equivalent depending on what provider you have.
   * @param layer should be an url or a javascript object with the data to create the layer
   * @param options layer options
   *
   */

  cartodb.createLayer = function(map, layer, options, callback) {
    if(map === undefined) {
      throw new TypeError("map should be provided");
    }
    if(layer === undefined) {
      throw new TypeError("layer should be provided");
    }

    var layerView, MapType;
    var options = options || {};
    var args = arguments;
    var fn = args[args.length -1];
    if(_.isFunction(fn)) {
      callback = fn;
    }
    var promise = new _Promise();

    promise.addTo = function(map, position) {
      promise.on('done', function() {
        MapType.addLayerToMap(layerView, map, position);
      });
      return promise;
    };

    _getLayerJson(layer, function(visData) {

      var layerData;

      if(!visData) {
        promise.trigger('error');
        return;
      }

      // extract layer data from visualization data
      if(visData.layers) {
        if(visData.layers.length < 2) {
          promise.trigger('error', "visualization file does not contain layer info");
        }
        var idx = options.layerIndex === undefined ? 1: options.layerIndex;
        if(visData.layers.length <= idx) {
          promise.trigger('error', 'layerIndex out of bounds');
          return;
        }
        layerData = visData.layers[idx];
      } else {
        layerData = visData;
      }

      if(!layerData) {
        promise.trigger('error');
        return;
      }

      // update options
      if(options && !_.isFunction(options)) {
        layerData.options = layerData.options || {};
        _.extend(layerData.options, options);
      }

      options = _.defaults(options, {
        infowindow: true,
        https: false,
        legends: true,
        time_slider: true,
        tooltip: true
      });

      // check map type
      // TODO: improve checking
      if(typeof(map.overlayMapTypes) !== "undefined") {
        MapType = cdb.geo.GoogleMapsMapView;
        // check if leaflet is loaded globally
      } else if(map instanceof L.Map || (window.L && map instanceof window.L.Map)) {
        MapType = cdb.geo.LeafletMapView;
      } else {
        promise.trigger('error', "cartodb.js can't guess the map type");
        return promise;
      }

      // create a dummy viz
      var viz = map.viz;
      if(!viz) {
        var mapView = new MapType({
          map_object: map,
          map: new cdb.geo.Map()
        });

        map.viz = viz = new cdb.vis.Vis({
          mapView: mapView
        });

        viz.updated_at = visData.updated_at;
        viz.https = options.https;
      }

      function createLayer() {
        layerView = viz.createLayer(layerData, { no_base_layer: true });

        var torqueLayer;
        var mobileEnabled = /Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
        var addMobileLayout = (options.mobile_layout && mobileEnabled) || options.force_mobile;

        if(!layerView) {
          promise.trigger('error', "layer not supported");
          return promise;
        }

        if(options.infowindow) {
          viz.addInfowindow(layerView);
        }

        if(options.tooltip) {
          viz.addTooltip(layerView);
        }

        if(options.legends) {
          var layerModel = cdb.vis.Layers.create(layerData.type || layerData.kind, viz, layerData);

          viz._addLegends(viz._createLayerLegendView(layerModel.attributes,  layerView))
        }

        if(options.time_slider && layerView.model.get('type') === 'torque') {

          if (!addMobileLayout) { // don't add the overlay if we are in mobile
            viz.addTimeSlider(layerView);
          }

          torqueLayer = layerView;
        }

        if (addMobileLayout) {

          options.mapView = map.viz.mapView;

          viz.addOverlay({
            type: 'mobile',
            layerView: layerView,
            overlays: [],
            torqueLayer: torqueLayer,
            options: options
          });
        }

        callback && callback(layerView);
        promise.trigger('done', layerView);
      }

      // load needed modules
      if(!viz.checkModules([layerData])) {
        viz.loadModules([layerData], function() {
          createLayer();
        });
      } else {
        createLayer();
      }

    });

    return promise;
  };

})();
<commit_msg>Revert "stays just with the else"<commit_after>/**
 * public api for cartodb
 */

(function() {

  function _Promise() {

  }
  _.extend(_Promise.prototype,  Backbone.Events, {
    done: function(fn) {
      return this.bind('done', fn);
    },
    error: function(fn) {
      return this.bind('error', fn);
    }
  });

  cdb._Promise = _Promise;

  var _requestCache = {};

  /**
   * compose cartodb url
   */
  function cartodbUrl(opts) {
    var host = opts.host || 'cartodb.com';
    var protocol = opts.protocol || 'https';
    return protocol + '://' + opts.user + '.' + host + '/api/v1/viz/' + opts.table + '/viz.json';
  }

  /**
   * given layer params fetchs the layer json
   */
  function _getLayerJson(layer, callback) {
    var url = null;
    if(layer.layers !== undefined || ((layer.kind || layer.type) !== undefined)) {
      // layer object contains the layer data
      _.defer(function() { callback(layer); });
      return;
    } else if(layer.table !== undefined && layer.user !== undefined) {
      // layer object points to cartodbjson
      url = cartodbUrl(layer);
    } else if(layer.indexOf) {
      // fetch from url
      url = layer;
    }
    if(url) {
      cdb.core.Loader.get(url, callback);
    } else {
      _.defer(function() { callback(null); });
    }
  }

  /**
   * create a layer for the specified map
   *
   * @param map should be a L.Map object, or equivalent depending on what provider you have.
   * @param layer should be an url or a javascript object with the data to create the layer
   * @param options layer options
   *
   */

  cartodb.createLayer = function(map, layer, options, callback) {
    if(map === undefined) {
      throw new TypeError("map should be provided");
    }
    if(layer === undefined) {
      throw new TypeError("layer should be provided");
    }

    var layerView, MapType;
    var options = options || {};
    var args = arguments;
    var fn = args[args.length -1];
    if(_.isFunction(fn)) {
      callback = fn;
    }
    var promise = new _Promise();

    promise.addTo = function(map, position) {
      promise.on('done', function() {
        MapType.addLayerToMap(layerView, map, position);
      });
      return promise;
    };

    _getLayerJson(layer, function(visData) {

      var layerData;

      if(!visData) {
        promise.trigger('error');
        return;
      }

      // extract layer data from visualization data
      if(visData.layers) {
        if(visData.layers.length < 2) {
          promise.trigger('error', "visualization file does not contain layer info");
        }
        var idx = options.layerIndex === undefined ? 1: options.layerIndex;
        if(visData.layers.length <= idx) {
          promise.trigger('error', 'layerIndex out of bounds');
          return;
        }
        layerData = visData.layers[idx];
      } else {
        layerData = visData;
      }

      if(!layerData) {
        promise.trigger('error');
        return;
      }

      // update options
      if(options && !_.isFunction(options)) {
        layerData.options = layerData.options || {};
        _.extend(layerData.options, options);
      }

      options = _.defaults(options, {
        infowindow: true,
        https: false,
        legends: true,
        time_slider: true,
        tooltip: true
      });

      // check map type
      // TODO: improve checking
      if(typeof(map.overlayMapTypes) !== "undefined") {
        MapType = cdb.geo.GoogleMapsMapView;
        // check if leaflet is loaded globally
      } else if(map instanceof L.Map || (window.L && map instanceof window.L.Map)) {
        MapType = cdb.geo.LeafletMapView;
      } else {
        promise.trigger('error', "cartodb.js can't guess the map type");
        return promise;
      }

      // create a dummy viz
      var viz = map.viz;
      if(!viz) {
        var mapView = new MapType({
          map_object: map,
          map: new cdb.geo.Map()
        });

        map.viz = viz = new cdb.vis.Vis({
          mapView: mapView
        });

        viz.updated_at = visData.updated_at;
        viz.https = options.https;
      }

      function createLayer() {
        layerView = viz.createLayer(layerData, { no_base_layer: true });

        var torqueLayer;
        var mobileEnabled = /Android|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
        var addMobileLayout = (options.mobile_layout && mobileEnabled) || options.force_mobile;

        if(!layerView) {
          promise.trigger('error', "layer not supported");
          return promise;
        }

        if(options.infowindow) {
          viz.addInfowindow(layerView);
        }

        if(options.tooltip) {
          viz.addTooltip(layerView);
        }

        if(options.legends) {
          var layerModel = cdb.vis.Layers.create(layerData.type || layerData.kind, viz, layerData);

          viz._addLegends(viz._createLayerLegendView(layerModel.attributes,  layerView))
        }

        if(options.time_slider && layerView.model.get('type') === 'torque') {

          if (!addMobileLayout) { // don't add the overlay if we are in mobile
            viz.addTimeSlider(layerView);
          }

          torqueLayer = layerView;
        }

        if (addMobileLayout) {

          options.mapView = map.viz.mapView;

          viz.addOverlay({
            type: 'mobile',
            layerView: layerView,
            overlays: [],
            torqueLayer: torqueLayer,
            options: options
          });
        }

        callback && callback(layerView);
        promise.trigger('done', layerView);
      }

      // load needed modules
      if(!viz.checkModules([layerData])) {
        viz.loadModules([layerData], function() {
          createLayer();
        });
      } else {
        createLayer();
      }

    });

    return promise;
  };

})();
<|endoftext|>


<commit_before>define([
    'dojo/_base/declare',
    'dojo/_base/lang',
    'dojo/_base/Color',
    'dojo/_base/array',

    'dojo/topic',
    'dojo/aspect',
    'dojo/on',
    'dojo/dom-class',

    'dijit/_WidgetBase',
    'dijit/_TemplatedMixin',
    'dijit/_WidgetsInTemplateMixin',

    'dijit/Tooltip',

    'dojo/text!app/templates/Editor.html',
    'dojo/i18n!esri/nls/jsapi', //this is where esri.bundle is located

    'esri/undoManager',
    'esri/toolbars/draw',
    'esri/graphic',
    'esri/tasks/query',
    'esri/toolbars/edit',
    'esri/symbols/SimpleMarkerSymbol',
    'esri/symbols/SimpleLineSymbol',
    'esri/dijit/editing/Add',
    'esri/dijit/editing/Delete',
    'esri/dijit/editing/Update',

    'app/config'
], function(
    declare,
    lang,
    Color,
    array,

    topic,
    aspect,
    on,
    domClass,

    _WidgetBase,
    _TemplatedMixin,
    _WidgetsInTemplateMixin,

    Tooltip,

    template,
    jsapiBundle,

    UndoManager,
    Draw,
    Graphic,
    Query,
    Edit,
    SimpleMarkerSymbol,
    SimpleLineSymbol,
    Add,
    Delete,
    Update,

    config
) {
    // summary:
    //      Handles retrieving and displaying the data in the popup.
    return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
        baseClass: 'editor-panel',

        widgetsInTemplate: true,

        templateString: template,

        // attribute maps
        undoCount: 0,
        _setUndoCountAttr: {
            node: 'undoCountSpan',
            type: 'innerHTML'
        },

        redoCount: 0,
        _setRedoCountAttr: {
            node: 'redoCountSpan',
            type: 'innerHTML'
        },

        //drawingToolbar: esri/toolbars/draw: the toolbar used to add new points

        //boolean: for knowing when drawing toolbar is active.
        //          allows for point button to be clicked twice to disable
        isDrawing: false,

        //esri/toolbars/edit: the toolbar controlling editing of the editLayer
        editingToolbar: null,

        //esri/layers/FeatureLayer: the feature layer being edited
        editLayer: null,

        //boolean: flag for knowing to start/finish editing session
        isEditing: null,

        //esri/Graphic: the graphic being edited. Holds the new location if being moved.
        updatedGraphic: null,

        //esri/Graphic: the original state of the updatedGraphic. Necessary for preUpdate on undomanager
        originalGraphic: null,

        //esri/Grahpic: the graphic to be displayed when adding a new point and waiting for the edit layer to draw it
        newGraphic: null,

        //dojo/event
        editingSignal: null,

        //esri/symbols/simplemarkersymbol: the color to make selected points for editing
        symbol: null,

        //esri/undomanager: the tool for enabling undo/redo
        undoManager: null,

        //moveText: domNode: the text displayed for starting and stopping editing points

        //hash: holds the edits as a key value pair with the objectid being the key and the
        //      value being original graphic and the moved graphic
        editSession: null,

        _setMoveTextAttr: {
            node: 'moveTextNode',
            type: 'innerHTML'
        },
        postCreate: function() {
            // summary:
            //      dom is ready
            console.info('app.editor::postCreate', arguments);

            this.inherited(arguments);

            this.editSession = {};

            this.symbol = new SimpleMarkerSymbol(
                SimpleMarkerSymbol.STYLE_CIRCLE, 8,
                new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
                    new Color('black'), 1),
                new Color('yellow')
            );

            this.undoManager = new UndoManager({
                maxOperations: 5
            });

            new Tooltip({
                connectId: [this.pointButton],
                label: 'Add address points to the map.'
            });

            new Tooltip({
                connectId: [this.moveButton],
                label: 'Enable moving of address points on the map. Hover over a point, then drag to move it.'
            });

            new Tooltip({
                connectId: [this.undoNode],
                label: 'Make a mistake? Undo the last editing action.'
            });

            new Tooltip({
                connectId: [this.redoNode],
                label: 'Redo the last editing action.'
            });

            jsapiBundle.toolbars.draw.addPoint = 'Click on the map to place your new address point.';

            this.drawingToolbar = new Draw(this.map);

            this.isEditing = false;

            this.editingToolbar = new Edit(this.map);

            this.wireEvents();
        },
        wireEvents: function() {
            // summary:
            //      sets up the events for this widget
            console.log('app.editor::wireEvents', arguments);

            //This assists the application to know what toolbar is active.
            this.own(
                aspect.after(this.drawingToolbar, 'deactivate', function() {
                    topic.publish('app/toolbar', 'navigation');
                }),
                aspect.after(this.drawingToolbar, 'activate', function() {
                    topic.publish('app/toolbar', 'drawing');
                }),
                aspect.after(this.editingToolbar, 'deactivate', function() {
                    topic.publish('app/toolbar', 'navigation');
                }),
                aspect.after(this.editingToolbar, 'activate', function() {
                    topic.publish('app/toolbar', 'editing');
                })
            );

            //Prelogic for activateEditing.
            this.own(
                aspect.before(this, 'activateEditing', function() {
                    this.drawingToolbar.deactivate();
                })
            );

            this.own(
                this.drawingToolbar.on('draw-end', lang.hitch(this, 'saveNewPoint')),

                //Prelogic for saveNewPoint
                aspect.before(this, 'saveNewPoint', function() {
                    this.isDrawing = false;
                    this.drawingToolbar.deactivate();
                    this.editLayer.clearSelection();

                    topic.publish('map-activity', 1);
                })
            );

            this.own(
                on(this.undoNode, 'click', lang.hitch(this, 'undo')),
                on(this.redoNode, 'click', lang.hitch(this, 'redo')),

                topic.subscribe('app/operation-edit', lang.hitch(this, 'addUndoState'))
            );

            this.own(
                topic.subscribe('app/save-edits', lang.hitch(this, 'saveEditsGeneric')),
                this.editingToolbar.on('deactivate', lang.hitch(this, 'saveMoveEdits'))
            );
        },
        saveNewPoint: function(evt) {
            // summary:
            //      applies the edits to the feature layer
            console.log('app.editor::wireEvents', arguments);

            this.newGraphic = new Graphic(evt.geometry, this.symbol, null, null);
            this.map.graphics.add(this.newGraphic);

            var selectQuery = new Query();
            selectQuery.geometry = evt.geometry;

            var context = this;

            topic.publish('app/save-edits', 'add', {
                    adds: [this.newGraphic],
                    updates: null,
                    deletes: null,
                    news: this.newGraphic,
                    original: null
                },
                function() {
                    console.log('success');
                    topic.publish('app/selectFeature', selectQuery);
                },
                null,
                function() {
                    console.log('always');
                    context.map.graphics.remove(context.newGraphic);
                    context.newGraphic = null;
                }
            );
        },
        activatePointDrawing: function() {
            // summary:
            //      enables the toolbar to edit points
            console.log('app.editor::activatePointDrawing', arguments);

            if (this.isDrawing) {
                this.drawingToolbar.deactivate();
                return;
            }

            this.isDrawing = true;
            this.drawingToolbar.activate(Draw.POINT);
        },
        activateEditing: function(/*evt*/ ) {
            // summary:
            //      sets up the evetns on the layer
            // layer: the layer added to the map that is going to be edited
            console.log('app.editor::activateEditing', arguments);

            this.set('moveText', 'Done');

            if (this.editingSignal) {
                this.editingToolbar.deactivate();
                this.editingSignal.remove();
                this.editingSignal = null;

                if (this.updatedGraphic) {
                    this.updatedGraphic.setSymbol(null);
                }

                this.set('moveText', 'Move');
                topic.publish('app/state', 'editing-finished');

                return;
            }

            topic.publish('app/state', 'editing-started');

            this.own(
                this.editingToolbar.on('graphic-move-stop', lang.hitch(this, 'updateMovingGraphic')),
                this.editingSignal = this.editLayer.on('mouse-over', lang.hitch(this, 'editPoint'))
            );
        },
        updateMovingGraphic: function(evt) {
            // summary:
            //      updates the location of an editing point graphic
            // evt: the mouse event from grahpic-move-stop
            console.log('app.editor::updateMovingGraphic', arguments);

            this.updatedGraphic = evt.graphic;
        },
        editPoint: function(evt) {
            // summary:
            //      handles the selection of points and enables/removes the editing functionality
            // evt: mouse event from the editingLayer's mouse-over evetn
            console.log('app.editor::editPoint', arguments);

            //do nothing if the current editing graphic is already selected.
            //this happens if mouse-over happens to the already selected graphic
            //while moving or deciding where to put the point.
            if (this.updatedGraphic !== evt.graphic) {

                if (this.updatedGraphic) {
                    //remove highlighting and stop editing the last graphic
                    this.updatedGraphic.setSymbol(null);
                    this.editingToolbar.deactivate(this.updatedGraphic);
                }

                //highlight and activate editing on new graphic
                evt.graphic.setSymbol(this.symbol);
                this.editingToolbar.activate(Edit.MOVE, evt.graphic);

                //store pre and post graphic for undo manager
                this.updatedGraphic = evt.graphic;

                //cloning original
                this.originalGraphic = new Graphic(evt.graphic.toJson());
            }
        },
        saveEditsGeneric: function(type, edits, successBack, errorBack, alwaysBack) {
            // summary:
            //      saves edits
            // type: string: update, edit or delete
            // edits: object: containings the edits
            //        {adds: [],
            //        updates: [],
            //        deletes: [],
            //        news: contains the new/updated graphic, original: contains the original}
            //        null if empty
            // successBack: function: executed on success
            // errorBack: function: executed on error
            // alwaysBack: function: executed always
            console.log('app.editor::saveEditsGeneric', arguments);

            //check on update if anything changed
            if (type === 'update') {
                if (edits.original.toJson() === edits.news.toJson()) {
                    //nothing to update, they are the same.
                    console.log('edits are the same skipping');
                    topic.publish('app/state', 'Skipping save. Items are the same.');

                    return;
                }
            }

            //display activity
            console.log('displaying activity');
            topic.publish('map-activity', 1);

            //modify callbacks
            console.log('modifiying activity');
            var modifiedSuccess = function(response) {
                console.log('modified success');

                var error;
                var check = function (edits) {
                    return array.every(edits, function (e) {
                        if (!e.success) {
                            error = e.error;
                        }
                        return e.success;
                    });
                };

                if (check(response.adds) &&
                    check(response.deletes) &&
                    check(response.updates)) {

                    topic.publish('app/operation-edit', type, edits.news, edits.original);
                    topic.publish('app/state', 'Edit saved successfully');

                    if (lang.isFunction(successBack)) {
                        successBack(response);
                    }
                } else {
                    modifiedError(error);
                }
            };

            var modifiedError = function(err) {
                console.log('modified error');
                var message = '';
                if (err && err.details && lang.isArray(err.details)) {
                    message = err.details[0];
                }

                topic.publish('app/state', 'Unable to save. ' + message);

                if (lang.isFunction(errorBack)) {
                    errorBack(err);
                }
            };

            var modifiedAlways = function(response) {
                console.log('modified always');
                topic.publish('map-activity', -1);

                if (lang.isFunction(alwaysBack)) {
                    alwaysBack(response);
                }
            };

            this.applyEditTracking(edits);

            //apply edits
            this.editLayer.applyEdits(edits.adds, edits.updates, edits.deletes)
                .then(null, modifiedError)
                .always(modifiedAlways);

            // couldn't get the correct response object by passing modifiedSuccess to
            // then above. Had to wire it to the event.
            this.editLayer.on('edits-complete', modifiedSuccess);
        },
        applyEditTracking: function (edits) {
            // summary:
            //      adds user name and current date to edit tracking fields
            // edits: object: containings the edits
            //        {adds: [],
            //        updates: [],
            //        deletes: []
            console.log('app.editor:applyEditTracking', arguments);

            var addAttributes = function (features) {
                array.forEach(features, function (f) {
                    f.attributes[config.fieldNames.Editor] = AGRC.user.email;
                    f.attributes[config.fieldNames.ModifyDate] = Date.now();
                });
            };

            addAttributes(edits.adds);
            addAttributes(edits.updates);
        },
        saveMoveEdits: function() {
            // summary:
            //      determines what edits to send to the server
            console.log('app.editor::saveMoveEdits', arguments);

            topic.publish('map-activity', 1);

            topic.publish('app/save-edits', 'update', {
                    adds: null,
                    updates: [this.updatedGraphic],
                    deletes: null,
                    news: this.updatedGraphic,
                    original: this.originalGraphic
                },
                null,
                null,
                null
            );
        },
        addUndoState: function(operationType, graphic, original) {
            // summary:
            //      handles edit operations/add/delete/update
            // operationType: string: add, update, delete
            // graphic: esri/graphic: the new grahpic
            // original: esri/graphic: the original graphic
            console.log('app.editor::addUndoState', arguments);

            var operation;

            switch (operationType) {
                case 'add':
                    operation = new Add({
                        addedGraphics: [graphic],
                        featureLayer: this.editLayer
                    });
                    break;
                case 'delete':
                    operation = new Delete({
                        deletedGraphics: [graphic],
                        featureLayer: this.editLayer
                    });
                    break;
                case 'update':
                    operation = new Update({
                        preUpdatedGraphics: [original],
                        postUpdatedGraphics: [graphic],
                        featureLayer: this.editLayer
                    });
            }

            console.log(operation);
            this.undoManager.add(operation);
            domClass.remove(this.undoNode, 'disabled');
            this.updateUndoRedoCounts();
        },
        undo: function(/*evt*/ ) {
            // summary:
            //      undo edit operation
            // evt: the mouse click event
            console.log('app.editor::undo', arguments);

            if (!this.undoManager.canUndo) {
                console.log('nothing to undo');

                return;
            }

            //undo redo don't return promise. can't show activity
            //topic.publish('map-activity', 1);

            this.undoManager.undo();
            this.updateUndoRedoCounts();
        },
        redo: function(/*evt*/ ) {
            // summary:
            //      redo operations
            // evt: the mouse click event
            console.log('app.editor::redo', arguments);

            if (!this.undoManager.canRedo) {
                console.log('nothing to redo');

                return;
            }

            //undo redo don't return promise. can't shot activity
            //topic.publish('map-activity', 1);

            this.undoManager.redo();
            this.updateUndoRedoCounts();
        },
        updateUndoRedoCounts: function() {
            // summary:
            //      updates the count bubbles next to the undo and redo buttons
            console.log('app.editor::updateUndoRedoCounts', arguments);

            var position = this.undoManager.position;
            var len = this.undoManager.length;
            var undo = (position === 0) ? '' : position;
            var redo = (len - position === 0) ? '' : len - position;

            this.set('undoCount', undo);
            this.set('redoCount', redo);

            if (this.get('undoCount') < 1) {
                domClass.add(this.undoNode, 'disabled');
                domClass.remove(this.redoNode, 'disabled');
            } else {
                domClass.add(this.redoNode, 'disabled');
                domClass.remove(this.undoNode, 'disabled');
            }
        }
    });
});
<commit_msg>Fixed bug causing unnecessary calls to applyEdits when selecting features with the move tool.<commit_after>define([
    'dojo/_base/declare',
    'dojo/_base/lang',
    'dojo/_base/Color',
    'dojo/_base/array',

    'dojo/topic',
    'dojo/aspect',
    'dojo/on',
    'dojo/dom-class',

    'dijit/_WidgetBase',
    'dijit/_TemplatedMixin',
    'dijit/_WidgetsInTemplateMixin',

    'dijit/Tooltip',

    'dojo/text!app/templates/Editor.html',
    'dojo/i18n!esri/nls/jsapi', //this is where esri.bundle is located

    'esri/undoManager',
    'esri/toolbars/draw',
    'esri/graphic',
    'esri/tasks/query',
    'esri/toolbars/edit',
    'esri/symbols/SimpleMarkerSymbol',
    'esri/symbols/SimpleLineSymbol',
    'esri/dijit/editing/Add',
    'esri/dijit/editing/Delete',
    'esri/dijit/editing/Update',

    'app/config'
], function(
    declare,
    lang,
    Color,
    array,

    topic,
    aspect,
    on,
    domClass,

    _WidgetBase,
    _TemplatedMixin,
    _WidgetsInTemplateMixin,

    Tooltip,

    template,
    jsapiBundle,

    UndoManager,
    Draw,
    Graphic,
    Query,
    Edit,
    SimpleMarkerSymbol,
    SimpleLineSymbol,
    Add,
    Delete,
    Update,

    config
) {
    // summary:
    //      Handles retrieving and displaying the data in the popup.
    return declare([_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin], {
        baseClass: 'editor-panel',

        widgetsInTemplate: true,

        templateString: template,

        // attribute maps
        undoCount: 0,
        _setUndoCountAttr: {
            node: 'undoCountSpan',
            type: 'innerHTML'
        },

        redoCount: 0,
        _setRedoCountAttr: {
            node: 'redoCountSpan',
            type: 'innerHTML'
        },

        //drawingToolbar: esri/toolbars/draw: the toolbar used to add new points

        //boolean: for knowing when drawing toolbar is active.
        //          allows for point button to be clicked twice to disable
        isDrawing: false,

        //esri/toolbars/edit: the toolbar controlling editing of the editLayer
        editingToolbar: null,

        //esri/layers/FeatureLayer: the feature layer being edited
        editLayer: null,

        //boolean: flag for knowing to start/finish editing session
        isEditing: null,

        //esri/Graphic: the graphic being edited. Holds the new location if being moved.
        updatedGraphic: null,

        //esri/Graphic: the original state of the updatedGraphic. Necessary for preUpdate on undomanager
        originalGraphic: null,

        //esri/Grahpic: the graphic to be displayed when adding a new point and waiting for the edit layer to draw it
        newGraphic: null,

        //dojo/event
        editingSignal: null,

        //esri/symbols/simplemarkersymbol: the color to make selected points for editing
        symbol: null,

        //esri/undomanager: the tool for enabling undo/redo
        undoManager: null,

        //moveText: domNode: the text displayed for starting and stopping editing points

        //hash: holds the edits as a key value pair with the objectid being the key and the
        //      value being original graphic and the moved graphic
        editSession: null,

        _setMoveTextAttr: {
            node: 'moveTextNode',
            type: 'innerHTML'
        },
        postCreate: function() {
            // summary:
            //      dom is ready
            console.info('app.editor::postCreate', arguments);

            this.inherited(arguments);

            this.editSession = {};

            this.symbol = new SimpleMarkerSymbol(
                SimpleMarkerSymbol.STYLE_CIRCLE, 8,
                new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,
                    new Color('black'), 1),
                new Color('yellow')
            );

            this.undoManager = new UndoManager({
                maxOperations: 5
            });

            new Tooltip({
                connectId: [this.pointButton],
                label: 'Add address points to the map.'
            });

            new Tooltip({
                connectId: [this.moveButton],
                label: 'Enable moving of address points on the map. Hover over a point, then drag to move it.'
            });

            new Tooltip({
                connectId: [this.undoNode],
                label: 'Make a mistake? Undo the last editing action.'
            });

            new Tooltip({
                connectId: [this.redoNode],
                label: 'Redo the last editing action.'
            });

            jsapiBundle.toolbars.draw.addPoint = 'Click on the map to place your new address point.';

            this.drawingToolbar = new Draw(this.map);

            this.isEditing = false;

            this.editingToolbar = new Edit(this.map);

            this.wireEvents();
        },
        wireEvents: function() {
            // summary:
            //      sets up the events for this widget
            console.log('app.editor::wireEvents', arguments);

            //This assists the application to know what toolbar is active.
            this.own(
                aspect.after(this.drawingToolbar, 'deactivate', function() {
                    topic.publish('app/toolbar', 'navigation');
                }),
                aspect.after(this.drawingToolbar, 'activate', function() {
                    topic.publish('app/toolbar', 'drawing');
                }),
                aspect.after(this.editingToolbar, 'deactivate', function() {
                    topic.publish('app/toolbar', 'navigation');
                }),
                aspect.after(this.editingToolbar, 'activate', function() {
                    topic.publish('app/toolbar', 'editing');
                })
            );

            //Prelogic for activateEditing.
            this.own(
                aspect.before(this, 'activateEditing', function() {
                    this.drawingToolbar.deactivate();
                })
            );

            this.own(
                this.drawingToolbar.on('draw-end', lang.hitch(this, 'saveNewPoint')),

                //Prelogic for saveNewPoint
                aspect.before(this, 'saveNewPoint', function() {
                    this.isDrawing = false;
                    this.drawingToolbar.deactivate();
                    this.editLayer.clearSelection();

                    topic.publish('map-activity', 1);
                })
            );

            this.own(
                on(this.undoNode, 'click', lang.hitch(this, 'undo')),
                on(this.redoNode, 'click', lang.hitch(this, 'redo')),

                topic.subscribe('app/operation-edit', lang.hitch(this, 'addUndoState'))
            );

            this.own(
                topic.subscribe('app/save-edits', lang.hitch(this, 'saveEditsGeneric')),
                this.editingToolbar.on('deactivate', lang.hitch(this, 'saveMoveEdits'))
            );
        },
        saveNewPoint: function(evt) {
            // summary:
            //      applies the edits to the feature layer
            console.log('app.editor::wireEvents', arguments);

            this.newGraphic = new Graphic(evt.geometry, this.symbol, null, null);
            this.map.graphics.add(this.newGraphic);

            var selectQuery = new Query();
            selectQuery.geometry = evt.geometry;

            var context = this;

            topic.publish('app/save-edits', 'add', {
                    adds: [this.newGraphic],
                    updates: null,
                    deletes: null,
                    news: this.newGraphic,
                    original: null
                },
                function() {
                    console.log('success');
                    topic.publish('app/selectFeature', selectQuery);
                },
                null,
                function() {
                    console.log('always');
                    context.map.graphics.remove(context.newGraphic);
                    context.newGraphic = null;
                }
            );
        },
        activatePointDrawing: function() {
            // summary:
            //      enables the toolbar to edit points
            console.log('app.editor::activatePointDrawing', arguments);

            if (this.isDrawing) {
                this.drawingToolbar.deactivate();
                return;
            }

            this.isDrawing = true;
            this.drawingToolbar.activate(Draw.POINT);
        },
        activateEditing: function(/*evt*/ ) {
            // summary:
            //      sets up the evetns on the layer
            // layer: the layer added to the map that is going to be edited
            console.log('app.editor::activateEditing', arguments);

            this.set('moveText', 'Done');

            if (this.editingSignal) {
                this.editingToolbar.deactivate();
                this.editingSignal.remove();
                this.editingSignal = null;

                if (this.updatedGraphic) {
                    this.updatedGraphic.setSymbol(null);
                }

                this.set('moveText', 'Move');
                topic.publish('app/state', 'editing-finished');

                return;
            }

            topic.publish('app/state', 'editing-started');

            this.own(
                this.editingToolbar.on('graphic-move-stop', lang.hitch(this, 'updateMovingGraphic')),
                this.editingSignal = this.editLayer.on('mouse-over', lang.hitch(this, 'editPoint'))
            );
        },
        updateMovingGraphic: function(evt) {
            // summary:
            //      updates the location of an editing point graphic
            // evt: the mouse event from grahpic-move-stop
            console.log('app.editor::updateMovingGraphic', arguments);

            this.updatedGraphic = evt.graphic;
        },
        editPoint: function(evt) {
            // summary:
            //      handles the selection of points and enables/removes the editing functionality
            // evt: mouse event from the editingLayer's mouse-over evetn
            console.log('app.editor::editPoint', arguments);

            //do nothing if the current editing graphic is already selected.
            //this happens if mouse-over happens to the already selected graphic
            //while moving or deciding where to put the point.
            if (this.updatedGraphic !== evt.graphic) {

                if (this.updatedGraphic) {
                    //remove highlighting and stop editing the last graphic
                    this.updatedGraphic.setSymbol(null);
                    this.editingToolbar.deactivate(this.updatedGraphic);
                }

                //highlight and activate editing on new graphic
                evt.graphic.setSymbol(this.symbol);
                this.editingToolbar.activate(Edit.MOVE, evt.graphic);

                //store pre and post graphic for undo manager
                this.updatedGraphic = evt.graphic;

                //cloning original
                this.originalGraphic = new Graphic(evt.graphic.toJson());
            }
        },
        saveEditsGeneric: function(type, edits, successBack, errorBack, alwaysBack) {
            // summary:
            //      saves edits
            // type: string: update, edit or delete
            // edits: object: containings the edits
            //        {adds: [],
            //        updates: [],
            //        deletes: [],
            //        news: contains the new/updated graphic, original: contains the original}
            //        null if empty
            // successBack: function: executed on success
            // errorBack: function: executed on error
            // alwaysBack: function: executed always
            console.log('app.editor::saveEditsGeneric', arguments);

            //check on update if anything changed
            if (type === 'update') {
                if (JSON.stringify(edits.original.geometry) === JSON.stringify(edits.news.geometry) &&
                    JSON.stringify(edits.original.attributes) === JSON.stringify(edits.news.attributes)) {
                    //nothing to update, they are the same.
                    console.log('edits are the same skipping');
                    topic.publish('app/state', 'Skipping save. Items are the same.');

                    return;
                }
            }

            //display activity
            console.log('displaying activity');
            topic.publish('map-activity', 1);

            //modify callbacks
            console.log('modifiying activity');
            var modifiedSuccess = function(response) {
                console.log('modified success');

                var error;
                var check = function (edits) {
                    return array.every(edits, function (e) {
                        if (!e.success) {
                            error = e.error;
                        }
                        return e.success;
                    });
                };

                if (check(response.adds) &&
                    check(response.deletes) &&
                    check(response.updates)) {

                    topic.publish('app/operation-edit', type, edits.news, edits.original);
                    topic.publish('app/state', 'Edit saved successfully');

                    if (lang.isFunction(successBack)) {
                        successBack(response);
                    }
                } else {
                    modifiedError(error);
                }
            };

            var modifiedError = function(err) {
                console.log('modified error');
                var message = '';
                if (err && err.details && lang.isArray(err.details)) {
                    message = err.details[0];
                }

                topic.publish('app/state', 'Unable to save. ' + message);

                if (lang.isFunction(errorBack)) {
                    errorBack(err);
                }
            };

            var modifiedAlways = function(response) {
                console.log('modified always');
                topic.publish('map-activity', -1);

                if (lang.isFunction(alwaysBack)) {
                    alwaysBack(response);
                }
            };

            this.applyEditTracking(edits);

            //apply edits
            this.editLayer.applyEdits(edits.adds, edits.updates, edits.deletes)
                .then(null, modifiedError)
                .always(modifiedAlways);

            // couldn't get the correct response object by passing modifiedSuccess to
            // then above. Had to wire it to the event.
            this.editLayer.on('edits-complete', modifiedSuccess);
        },
        applyEditTracking: function (edits) {
            // summary:
            //      adds user name and current date to edit tracking fields
            // edits: object: containings the edits
            //        {adds: [],
            //        updates: [],
            //        deletes: []
            console.log('app.editor:applyEditTracking', arguments);

            var addAttributes = function (features) {
                array.forEach(features, function (f) {
                    f.attributes[config.fieldNames.Editor] = AGRC.user.email;
                    f.attributes[config.fieldNames.ModifyDate] = Date.now();
                });
            };

            addAttributes(edits.adds);
            addAttributes(edits.updates);
        },
        saveMoveEdits: function() {
            // summary:
            //      determines what edits to send to the server
            console.log('app.editor::saveMoveEdits', arguments);

            topic.publish('map-activity', 1);

            topic.publish('app/save-edits', 'update', {
                    adds: null,
                    updates: [this.updatedGraphic],
                    deletes: null,
                    news: this.updatedGraphic,
                    original: this.originalGraphic
                },
                null,
                null,
                null
            );
        },
        addUndoState: function(operationType, graphic, original) {
            // summary:
            //      handles edit operations/add/delete/update
            // operationType: string: add, update, delete
            // graphic: esri/graphic: the new grahpic
            // original: esri/graphic: the original graphic
            console.log('app.editor::addUndoState', arguments);

            var operation;

            switch (operationType) {
                case 'add':
                    operation = new Add({
                        addedGraphics: [graphic],
                        featureLayer: this.editLayer
                    });
                    break;
                case 'delete':
                    operation = new Delete({
                        deletedGraphics: [graphic],
                        featureLayer: this.editLayer
                    });
                    break;
                case 'update':
                    operation = new Update({
                        preUpdatedGraphics: [original],
                        postUpdatedGraphics: [graphic],
                        featureLayer: this.editLayer
                    });
            }

            console.log(operation);
            this.undoManager.add(operation);
            domClass.remove(this.undoNode, 'disabled');
            this.updateUndoRedoCounts();
        },
        undo: function(/*evt*/ ) {
            // summary:
            //      undo edit operation
            // evt: the mouse click event
            console.log('app.editor::undo', arguments);

            if (!this.undoManager.canUndo) {
                console.log('nothing to undo');

                return;
            }

            //undo redo don't return promise. can't show activity
            //topic.publish('map-activity', 1);

            this.undoManager.undo();
            this.updateUndoRedoCounts();
        },
        redo: function(/*evt*/ ) {
            // summary:
            //      redo operations
            // evt: the mouse click event
            console.log('app.editor::redo', arguments);

            if (!this.undoManager.canRedo) {
                console.log('nothing to redo');

                return;
            }

            //undo redo don't return promise. can't shot activity
            //topic.publish('map-activity', 1);

            this.undoManager.redo();
            this.updateUndoRedoCounts();
        },
        updateUndoRedoCounts: function() {
            // summary:
            //      updates the count bubbles next to the undo and redo buttons
            console.log('app.editor::updateUndoRedoCounts', arguments);

            var position = this.undoManager.position;
            var len = this.undoManager.length;
            var undo = (position === 0) ? '' : position;
            var redo = (len - position === 0) ? '' : len - position;

            this.set('undoCount', undo);
            this.set('redoCount', redo);

            if (this.get('undoCount') < 1) {
                domClass.add(this.undoNode, 'disabled');
                domClass.remove(this.redoNode, 'disabled');
            } else {
                domClass.add(this.redoNode, 'disabled');
                domClass.remove(this.undoNode, 'disabled');
            }
        }
    });
});
<|endoftext|>


<commit_before>/**
 * Created by Abdellatif on 1/9/2017.
 */
var React = require('react');
var firebase = require('firebase');
import Paper from 'material-ui/Paper'
import FlatButton from 'material-ui/FlatButton';
import EventCard from './EventCard'
var key = 0;

export default class Events extends React.Component{
    getKey(){
        key++;
        return key;
    }

    handleExpandChange = (expanded) => {
    };

    handleExpand = () => {
        this.expandedForm = true;
    };

    reverseExpand(expanded){
        return !expanded;
    }
    handleReduce = () => {
        this.setState({expanded: false});
    };

    componentWillMount(){
        var database = firebase.database();
        var eventsRef = database.ref().root;
        eventsRef.on('value', snap => {
            var events = Object.values(snap.val());
            for (var i = 0; i < events.length; i++){
                events[i].expandedForm = false;
            }
            console.log(events)

            this.setState({
                events: events,
            })
        })
    }

    constructor(props) {
        super(props);

        this.state = {
            events: [],
            expanded: false,
        }
    }

    render() {

        const archiveStyle = {
            marginTop: 20,
        };

        var archivedEvents = (
        <FlatButton label="Events Archive" style={archiveStyle}/>
        );

        const cardTextExpanded = false;

        var events = this.state.events.map(event =>
        <EventCard key={this.getKey()} title={event.title} type={event.type} pictureURL={event.pictureURL} description={event.description}
        dayAndTime={event.dayAndTime} locationAndDate={event.locationAndDate} RSVP={event.RSVP}></EventCard>
        )
        // var events = this.state.events.map(event =>
        //

        //         <Card style={cardStyle} expanded={event.expanded} onExpandChange={this.handleExpandChange}>
        //             <CardHeader
        //                 title={event.title} titleStyle={titleStyle}
        //                 subtitle={event.type} subtitleStyle={subtitleStyle}
        //                 actAsExpander={true}
        //                 showExpandableButton={true}
        //             />
        //
        //             <CardText style={cardTextStyle} expandable={true}>
        //                 {event.description}
        //             </CardText>
        //             <CardTitle title={event.dayAndTime} subtitle={event.locationAndDate} titleStyle={titleStyle2} subtitleStyle={subtitleStyle} />
        //             <CardActions>
        //                 <FlatButton label="Description" primary={true} onTouchTap={this.handleExpand}/>
        //                 <FlatButton label="RSVP" secondary={true} href={event.RSVP} target="_window"/>
        //             </CardActions>
        //         </Card>
        //

        // );

        return (
            <Paper className="section" rounded={false} zDepth={1} id="events">

EVENTS

                    {events}

                    {archivedEvents}
            </Paper>
        );
    }
};

<commit_msg>remove comments for the old component<commit_after>/**
 * Created by Abdellatif on 1/9/2017.
 */
var React = require('react');
var firebase = require('firebase');
import Paper from 'material-ui/Paper'
import FlatButton from 'material-ui/FlatButton';
import EventCard from './EventCard'
var key = 0;

export default class Events extends React.Component{
    getKey(){
        key++;
        return key;
    }

    handleExpandChange = (expanded) => {
    };

    handleExpand = () => {
        this.expandedForm = true;
    };

    reverseExpand(expanded){
        return !expanded;
    }
    handleReduce = () => {
        this.setState({expanded: false});
    };

    componentWillMount(){
        var database = firebase.database();
        var eventsRef = database.ref().root;
        eventsRef.on('value', snap => {
            var events = Object.values(snap.val());
            for (var i = 0; i < events.length; i++){
                events[i].expandedForm = false;
            }

            this.setState({
                events: events,
            })
        })
    }

    constructor(props) {
        super(props);

        this.state = {
            events: [],
            expanded: false,
        }
    }

    render() {

        const archiveStyle = {
            marginTop: 20,
        };

        var archivedEvents = (
        <FlatButton label="Events Archive" style={archiveStyle}/>
        );

        const cardTextExpanded = false;

        var events = this.state.events.map(event =>
        <EventCard key={this.getKey()} title={event.title} type={event.type} pictureURL={event.pictureURL} description={event.description}
        dayAndTime={event.dayAndTime} locationAndDate={event.locationAndDate} RSVP={event.RSVP}></EventCard>
        );

        return (
            <Paper className="section" rounded={false} zDepth={1} id="events">

EVENTS

                    {events}

                    {archivedEvents}
            </Paper>
        );
    }
};

<|endoftext|>


<commit_before>'use strict'

var utils = require('./utils')

var CONFIG_FILE = utils.fileKey('.browser-solidity.json')

function Config (storage) {
  this.items = {}

  // load on instantiation
  var config = storage.get(CONFIG_FILE)
  if (config) {
    this.items = JSON.parse(config)
  }

  this.exists = function (key) {
    return this.items[key] !== undefined
  }

  this.get = function (key) {
    return this.items[key]
  }

  this.set = function (key, content) {
    this.items[key] = content
    storage.set(CONFIG_FILE, JSON.stringify(this.items))
  }
}

module.exports = Config
<commit_msg>Enclose JSON conversion in try/catch<commit_after>'use strict'

var utils = require('./utils')

var CONFIG_FILE = utils.fileKey('.browser-solidity.json')

function Config (storage) {
  this.items = {}

  // load on instantiation
  try {
    var config = storage.get(CONFIG_FILE)
    if (config) {
      this.items = JSON.parse(config)
    }
  } catch (exception) {
  }

  this.exists = function (key) {
    return this.items[key] !== undefined
  }

  this.get = function (key) {
    return this.items[key]
  }

  this.set = function (key, content) {
    this.items[key] = content
    try {
      storage.set(CONFIG_FILE, JSON.stringify(this.items))
    } catch (exception) {
    }
  }
}

module.exports = Config
<|endoftext|>


<commit_before>// json-schema for incoming font config validation
//
'use strict';

module.exports = {

  type: 'object',
  additionalProperties: false,
  required: true,
  properties: {
    name:             { type: 'string',   required: false, 'default': 'fontello' },
    css_prefix_text:  { type: 'string',   required: false, 'default': 'icon-' },
    css_use_suffix:   { type: 'boolean',  required: false, 'default': false },
    hinting:          { type: 'boolean',  required: false, 'default': false },
    units_per_em:     { type: 'integer',  required: false, 'default': 1000, minimum: 10 },
    ascent:           { type: 'integer',  required: false, 'default': 850,  minimum: 10 },
    fullname:         { type: 'string',   required: false },
    copyright:        { type: 'string',   required: false },
    glyphs: {
      type: 'array',
      minItems: 1,
      items: {
        oneOf: [
          // embedded glyph schema
          {
            type: 'object',
            additionalProperties: false,
            properties: {
              uid:  { type: 'string',  required: true },
              css:  { type: 'string',  required: true },
              code: { type: 'integer', required: true, minimum: 1 },
              src:  { type: 'string',  required: true }
            }
          },
          // custom icon schema
          {
            type: 'object',
            additionalProperties: false,
            properties: {
              uid:  { type: 'string',  required: true },
              css:  { type: 'string',  required: true },
              code: { type: 'integer', required: true,  minimum: 1 },
              src:  { type: 'string',  required: true,  pattern: /^custom_icons$/ },
              search: {
                type: 'array',
                required: false,
                items: { type: 'string' }
              },
              svg: {
                type: 'object',
                required: true,
                additionalProperties: false,
                properties: {
                  path:   { type: 'string',  required: true },
                  width:  { type: 'number', required: true,  minimum: 10 }
                }
              },
              selected: {
                type: 'boolean',
                required: false
              }
            }
          }
        ]
      }
    }
  }
};
<commit_msg>Relax config schema (closes #486)<commit_after>// json-schema for incoming font config validation
//
'use strict';

module.exports = {

  type: 'object',
  additionalProperties: false,
  required: true,
  properties: {
    name:             { type: 'string',   required: false, 'default': 'fontello' },
    css_prefix_text:  { type: 'string',   required: false, 'default': 'icon-' },
    css_use_suffix:   { type: 'boolean',  required: false, 'default': false },
    hinting:          { type: 'boolean',  required: false, 'default': false },
    units_per_em:     { type: 'integer',  required: false, 'default': 1000, minimum: 10 },
    ascent:           { type: 'integer',  required: false, 'default': 850,  minimum: 10 },
    fullname:         { type: 'string',   required: false },
    copyright:        { type: 'string',   required: false },
    glyphs: {
      type: 'array',
      minItems: 1,
      items: {
        oneOf: [
          // embedded glyph schema
          {
            type: 'object',
            additionalProperties: false,
            properties: {
              uid:  { type: 'string',  required: true },
              css:  { type: 'string',  required: true },
              code: { type: 'integer', required: true, minimum: 1 },
              src:  { type: 'string',  required: true }
            }
          },
          // custom icon schema
          {
            type: 'object',
            additionalProperties: false,
            properties: {
              uid:  { type: 'string',  required: true },
              css:  { type: 'string',  required: true },
              code: { type: 'integer', required: true,  minimum: 1 },
              src:  { type: 'string',  required: true,  pattern: /^custom_icons$/ },
              search: {
                type: 'array',
                required: false,
                items: { type: 'string' }
              },
              svg: {
                type: 'object',
                required: true,
                additionalProperties: false,
                properties: {
                  path:   { type: 'string',  required: true },
                  width:  { type: 'number', required: true,  minimum: 0 }
                }
              },
              selected: {
                type: 'boolean',
                required: false
              }
            }
          }
        ]
      }
    }
  }
};
<|endoftext|>