<commit_before>require('../support/test_helper');

var assert = require('assert');
var RedisPool = require('redis-mpool');
var TemplateMaps = require('../../lib/cartodb/backends/template_maps.js');
var PgConnection = require(__dirname + '/../../lib/cartodb/backends/pg_connection');
var MapConfigNamedLayersAdapter = require('../../lib/cartodb/models/mapconfig/adapter/mapconfig-named-layers-adapter');

// configure redis pool instance to use in tests
var redisPool = new RedisPool(global.environment.redis);
var pgConnection = new PgConnection(require('cartodb-redis')({ pool: redisPool }));

var templateMaps = new TemplateMaps(redisPool, {
    max_user_templates: global.environment.maxUserTemplates
});

var mapConfigNamedLayersAdapter = new MapConfigNamedLayersAdapter(templateMaps, pgConnection);

var wadusSql = 'select 1 wadusLayer, null::geometry the_geom_webmercator';
var wadusLayer = {
    type: 'cartodb',
    options: {
        sql: wadusSql,
        cartocss: '#layer { marker-fill: black; }',
        cartocss_version: '2.3.0'
    }
};

var wadusTemplateSql = 'select 1 wadusTemplateLayer, null::geometry the_geom_webmercator';
var wadusTemplateLayer = {
    type: 'cartodb',
    options: {
        sql: wadusTemplateSql,
        cartocss: '#layer { marker-fill: <%= color %>; }',
        cartocss_version: '2.3.0'
    }
};

var wadusMapnikSql = 'select 1 wadusMapnikLayer, null::geometry the_geom_webmercator';
var wadusMapnikLayer = {
    type: 'mapnik',
    options: {
        sql: wadusMapnikSql,
        cartocss: '#layer { polygon-fill: <%= polygon_color %>; }',
        cartocss_version: '2.3.0'
    }
};

var username = 'localhost';

var templateName = 'valid_template';
var template = {
    version: '0.0.1',
    name: templateName,
    auth: {
        method: 'open'
    },
    "placeholders": {
        "color": {
            "type": "css_color",
            "default": "#cc3300"
        }
    },
    layergroup: {
        layers: [
            wadusTemplateLayer
        ]
    }
};

var multipleLayersTemplateName = 'multiple_valid_template';
var multipleLayersTemplate = {
    version: '0.0.1',
    name: multipleLayersTemplateName,
    auth: {
        method: 'token',
        valid_tokens: ['valid1', 'valid2']
    },
    "placeholders": {
        "polygon_color": {
            "type": "css_color",
            "default": "green"
        },
        "color": {
            "type": "css_color",
            "default": "red"
        }
    },
    layergroup: {
        layers: [
            wadusMapnikLayer,
            wadusTemplateLayer
        ]
    }
};

describe('named_layers datasources', function() {
    beforeEach(function(done) {
        templateMaps.addTemplate(username, template, function(err) {
            if (err) {
                return done(err);
            }
            templateMaps.addTemplate(username, multipleLayersTemplate, done);
        });
    });

    afterEach(function(done) {
        templateMaps.delTemplate(username, templateName, function(err) {
            if (err) {
                return done(err);
            }
            templateMaps.delTemplate(username, multipleLayersTemplateName, done);
        });
    });

    function makeNamedMapLayerConfig(layers) {
        return {
            version: '1.3.0',
            layers: layers
        };
    }

    var simpleNamedLayer = {
        type: 'named',
        options: {
            name: templateName
        }
    };

    var multipleLayersNamedLayer = {
        type: 'named',
        options: {
            name: multipleLayersTemplateName,
            auth_tokens: ['valid2']
        }
    };

    var testScenarios = [
        {
            desc: 'without datasource for non-named layers',
            config: makeNamedMapLayerConfig([wadusLayer]),
            test: function(err, layers, datasource, done) {
                assert.ok(!err);
                assert.equal(layers.length, 1);

                assert.equal(layers[0].type, 'cartodb');
                assert.equal(layers[0].options.sql, wadusSql);
                assert.equal(datasource.getLayerDatasource(0), undefined);

                done();
            }
        },

        {
            desc: 'with datasource for the named layer but not for the normal',
            config: makeNamedMapLayerConfig([wadusLayer, simpleNamedLayer]),
            test: function(err, layers, datasource, done) {
                assert.ok(!err);
                assert.equal(layers.length, 2);

                assert.equal(layers[0].type, 'cartodb');
                assert.equal(layers[0].options.sql, wadusSql);
                assert.equal(datasource.getLayerDatasource(0), undefined);

                assert.equal(layers[1].type, 'cartodb');
                assert.equal(layers[1].options.sql, wadusTemplateSql);
                var layerDatasource = datasource.getLayerDatasource(1);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                done();
            }
        },

        {
            desc: 'with datasource for the multiple layers in the named but not for the normal',
            config: makeNamedMapLayerConfig([wadusLayer, multipleLayersNamedLayer]),
            test: function(err, layers, datasource, done) {
                assert.ok(!err);
                assert.equal(layers.length, 3);

                assert.equal(layers[0].type, 'cartodb');
                assert.equal(layers[0].options.sql, wadusSql);
                assert.equal(datasource.getLayerDatasource(0), undefined);

                assert.equal(layers[1].type, 'mapnik');
                assert.equal(layers[1].options.sql, wadusMapnikSql);
                var layerDatasource = datasource.getLayerDatasource(1);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                assert.equal(layers[2].type, 'cartodb');
                assert.equal(layers[2].options.sql, wadusTemplateSql);
                layerDatasource = datasource.getLayerDatasource(2);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                done();
            }
        },

        {
            desc: 'all with datasource because all are named',
            config: makeNamedMapLayerConfig([multipleLayersNamedLayer, simpleNamedLayer]),
            test: function(err, layers, datasource, done) {
                assert.ok(!err);
                assert.equal(layers.length, 3);

                assert.equal(layers[0].type, 'mapnik');
                assert.equal(layers[0].options.sql, wadusMapnikSql);
                var layerDatasource = datasource.getLayerDatasource(0);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                assert.equal(layers[1].type, 'cartodb');
                assert.equal(layers[1].options.sql, wadusTemplateSql);
                layerDatasource = datasource.getLayerDatasource(1);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                assert.equal(layers[2].type, 'cartodb');
                assert.equal(layers[2].options.sql, wadusTemplateSql);
                layerDatasource = datasource.getLayerDatasource(2);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                done();
            }
        },

        {
            desc: 'with a mix of datasource and no datasource depending if layers are named or not',
            config: makeNamedMapLayerConfig([
                simpleNamedLayer,
                multipleLayersNamedLayer,
                wadusLayer,
                simpleNamedLayer,
                wadusLayer,
                multipleLayersNamedLayer
            ]),
            test: function(err, layers, datasource, done) {

                assert.ok(!err);
                assert.equal(layers.length, 8);

                assert.equal(layers[0].type, 'cartodb');
                assert.equal(layers[0].options.sql, wadusTemplateSql);
                var layerDatasource = datasource.getLayerDatasource(0);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                assert.equal(layers[1].type, 'mapnik');
                assert.equal(layers[1].options.sql, wadusMapnikSql);
                layerDatasource = datasource.getLayerDatasource(1);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                assert.equal(layers[2].type, 'cartodb');
                assert.equal(layers[2].options.sql, wadusTemplateSql);
                layerDatasource = datasource.getLayerDatasource(2);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                assert.equal(layers[3].type, 'cartodb');
                assert.equal(layers[3].options.sql, wadusSql);
                assert.equal(datasource.getLayerDatasource(3), undefined);

                assert.equal(layers[4].type, 'cartodb');
                assert.equal(layers[4].options.sql, wadusTemplateSql);
                layerDatasource = datasource.getLayerDatasource(4);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                assert.equal(layers[5].type, 'cartodb');
                assert.equal(layers[5].options.sql, wadusSql);
                assert.equal(datasource.getLayerDatasource(5), undefined);

                assert.equal(layers[6].type, 'mapnik');
                assert.equal(layers[6].options.sql, wadusMapnikSql);
                layerDatasource = datasource.getLayerDatasource(6);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                assert.equal(layers[7].type, 'cartodb');
                assert.equal(layers[7].options.sql, wadusTemplateSql);
                layerDatasource = datasource.getLayerDatasource(7);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                done();
            }
        }
    ];

    testScenarios.forEach(function(testScenario) {
        it('should return a list of layers ' + testScenario.desc, function(done) {
            var params = {};
            var context = {};
            mapConfigNamedLayersAdapter.getMapConfig(username, testScenario.config, params, context,
                function(err, mapConfig) {
                    testScenario.test(err, mapConfig.layers, context.datasource, done);
                }
            );
        });
    });
});
<commit_msg>Fix assertions, now MapCofig.getLayer() return {} if layer not found<commit_after>require('../support/test_helper');

var assert = require('assert');
var RedisPool = require('redis-mpool');
var TemplateMaps = require('../../lib/cartodb/backends/template_maps.js');
var PgConnection = require(__dirname + '/../../lib/cartodb/backends/pg_connection');
var MapConfigNamedLayersAdapter = require('../../lib/cartodb/models/mapconfig/adapter/mapconfig-named-layers-adapter');

// configure redis pool instance to use in tests
var redisPool = new RedisPool(global.environment.redis);
var pgConnection = new PgConnection(require('cartodb-redis')({ pool: redisPool }));

var templateMaps = new TemplateMaps(redisPool, {
    max_user_templates: global.environment.maxUserTemplates
});

var mapConfigNamedLayersAdapter = new MapConfigNamedLayersAdapter(templateMaps, pgConnection);

var wadusSql = 'select 1 wadusLayer, null::geometry the_geom_webmercator';
var wadusLayer = {
    type: 'cartodb',
    options: {
        sql: wadusSql,
        cartocss: '#layer { marker-fill: black; }',
        cartocss_version: '2.3.0'
    }
};

var wadusTemplateSql = 'select 1 wadusTemplateLayer, null::geometry the_geom_webmercator';
var wadusTemplateLayer = {
    type: 'cartodb',
    options: {
        sql: wadusTemplateSql,
        cartocss: '#layer { marker-fill: <%= color %>; }',
        cartocss_version: '2.3.0'
    }
};

var wadusMapnikSql = 'select 1 wadusMapnikLayer, null::geometry the_geom_webmercator';
var wadusMapnikLayer = {
    type: 'mapnik',
    options: {
        sql: wadusMapnikSql,
        cartocss: '#layer { polygon-fill: <%= polygon_color %>; }',
        cartocss_version: '2.3.0'
    }
};

var username = 'localhost';

var templateName = 'valid_template';
var template = {
    version: '0.0.1',
    name: templateName,
    auth: {
        method: 'open'
    },
    "placeholders": {
        "color": {
            "type": "css_color",
            "default": "#cc3300"
        }
    },
    layergroup: {
        layers: [
            wadusTemplateLayer
        ]
    }
};

var multipleLayersTemplateName = 'multiple_valid_template';
var multipleLayersTemplate = {
    version: '0.0.1',
    name: multipleLayersTemplateName,
    auth: {
        method: 'token',
        valid_tokens: ['valid1', 'valid2']
    },
    "placeholders": {
        "polygon_color": {
            "type": "css_color",
            "default": "green"
        },
        "color": {
            "type": "css_color",
            "default": "red"
        }
    },
    layergroup: {
        layers: [
            wadusMapnikLayer,
            wadusTemplateLayer
        ]
    }
};

describe('named_layers datasources', function() {
    beforeEach(function(done) {
        templateMaps.addTemplate(username, template, function(err) {
            if (err) {
                return done(err);
            }
            templateMaps.addTemplate(username, multipleLayersTemplate, done);
        });
    });

    afterEach(function(done) {
        templateMaps.delTemplate(username, templateName, function(err) {
            if (err) {
                return done(err);
            }
            templateMaps.delTemplate(username, multipleLayersTemplateName, done);
        });
    });

    function makeNamedMapLayerConfig(layers) {
        return {
            version: '1.3.0',
            layers: layers
        };
    }

    var simpleNamedLayer = {
        type: 'named',
        options: {
            name: templateName
        }
    };

    var multipleLayersNamedLayer = {
        type: 'named',
        options: {
            name: multipleLayersTemplateName,
            auth_tokens: ['valid2']
        }
    };

    var testScenarios = [
        {
            desc: 'without datasource for non-named layers',
            config: makeNamedMapLayerConfig([wadusLayer]),
            test: function(err, layers, datasource, done) {
                assert.ok(!err);
                assert.equal(layers.length, 1);

                assert.equal(layers[0].type, 'cartodb');
                assert.equal(layers[0].options.sql, wadusSql);
                assert.deepEqual(datasource.getLayerDatasource(0), {});

                done();
            }
        },

        {
            desc: 'with datasource for the named layer but not for the normal',
            config: makeNamedMapLayerConfig([wadusLayer, simpleNamedLayer]),
            test: function(err, layers, datasource, done) {
                assert.ok(!err);
                assert.equal(layers.length, 2);

                assert.equal(layers[0].type, 'cartodb');
                assert.equal(layers[0].options.sql, wadusSql);
                assert.deepEqual(datasource.getLayerDatasource(0), {});

                assert.equal(layers[1].type, 'cartodb');
                assert.equal(layers[1].options.sql, wadusTemplateSql);
                var layerDatasource = datasource.getLayerDatasource(1);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                done();
            }
        },

        {
            desc: 'with datasource for the multiple layers in the named but not for the normal',
            config: makeNamedMapLayerConfig([wadusLayer, multipleLayersNamedLayer]),
            test: function(err, layers, datasource, done) {
                assert.ok(!err);
                assert.equal(layers.length, 3);

                assert.equal(layers[0].type, 'cartodb');
                assert.equal(layers[0].options.sql, wadusSql);
                assert.deepEqual(datasource.getLayerDatasource(0), {});

                assert.equal(layers[1].type, 'mapnik');
                assert.equal(layers[1].options.sql, wadusMapnikSql);
                var layerDatasource = datasource.getLayerDatasource(1);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                assert.equal(layers[2].type, 'cartodb');
                assert.equal(layers[2].options.sql, wadusTemplateSql);
                layerDatasource = datasource.getLayerDatasource(2);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                done();
            }
        },

        {
            desc: 'all with datasource because all are named',
            config: makeNamedMapLayerConfig([multipleLayersNamedLayer, simpleNamedLayer]),
            test: function(err, layers, datasource, done) {
                assert.ok(!err);
                assert.equal(layers.length, 3);

                assert.equal(layers[0].type, 'mapnik');
                assert.equal(layers[0].options.sql, wadusMapnikSql);
                var layerDatasource = datasource.getLayerDatasource(0);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                assert.equal(layers[1].type, 'cartodb');
                assert.equal(layers[1].options.sql, wadusTemplateSql);
                layerDatasource = datasource.getLayerDatasource(1);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                assert.equal(layers[2].type, 'cartodb');
                assert.equal(layers[2].options.sql, wadusTemplateSql);
                layerDatasource = datasource.getLayerDatasource(2);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                done();
            }
        },

        {
            desc: 'with a mix of datasource and no datasource depending if layers are named or not',
            config: makeNamedMapLayerConfig([
                simpleNamedLayer,
                multipleLayersNamedLayer,
                wadusLayer,
                simpleNamedLayer,
                wadusLayer,
                multipleLayersNamedLayer
            ]),
            test: function(err, layers, datasource, done) {

                assert.ok(!err);
                assert.equal(layers.length, 8);

                assert.equal(layers[0].type, 'cartodb');
                assert.equal(layers[0].options.sql, wadusTemplateSql);
                var layerDatasource = datasource.getLayerDatasource(0);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                assert.equal(layers[1].type, 'mapnik');
                assert.equal(layers[1].options.sql, wadusMapnikSql);
                layerDatasource = datasource.getLayerDatasource(1);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                assert.equal(layers[2].type, 'cartodb');
                assert.equal(layers[2].options.sql, wadusTemplateSql);
                layerDatasource = datasource.getLayerDatasource(2);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                assert.equal(layers[3].type, 'cartodb');
                assert.equal(layers[3].options.sql, wadusSql);
                assert.deepEqual(datasource.getLayerDatasource(3), {});

                assert.equal(layers[4].type, 'cartodb');
                assert.equal(layers[4].options.sql, wadusTemplateSql);
                layerDatasource = datasource.getLayerDatasource(4);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                assert.equal(layers[5].type, 'cartodb');
                assert.equal(layers[5].options.sql, wadusSql);
                assert.deepEqual(datasource.getLayerDatasource(5), {});

                assert.equal(layers[6].type, 'mapnik');
                assert.equal(layers[6].options.sql, wadusMapnikSql);
                layerDatasource = datasource.getLayerDatasource(6);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                assert.equal(layers[7].type, 'cartodb');
                assert.equal(layers[7].options.sql, wadusTemplateSql);
                layerDatasource = datasource.getLayerDatasource(7);
                assert.notEqual(layerDatasource, undefined);
                assert.ok(layerDatasource.user);

                done();
            }
        }
    ];

    testScenarios.forEach(function(testScenario) {
        it('should return a list of layers ' + testScenario.desc, function(done) {
            var params = {};
            var context = {};
            mapConfigNamedLayersAdapter.getMapConfig(username, testScenario.config, params, context,
                function(err, mapConfig) {
                    assert.ifError(err);
                    testScenario.test(err, mapConfig.layers, context.datasource, done);
                }
            );
        });
    });
});
<|endoftext|>


<commit_before>const expect = require('chai').expect
const eligiblityHelper = require('../../../helpers/data/eligibility-helper')
const visitorHelper = require('../../../helpers/data/visitor-helper')
const insertVisitor = require('../../../../app/services/data/insert-visitor')
const dateFormatter = require('../../../../app/services/date-formatter')

describe('services/data/insert-visitor', function () {
  var REFERENCE = 'V123456'
  var eligibilityId

  before(function () {
    return eligiblityHelper.insert(REFERENCE)
      .then(function (newEligibilityId) {
        eligibilityId = newEligibilityId
      })
  })

  it('should insert a new Visitor for a reference', function () {
    var visitorInserted = visitorHelper.build()
    return insertVisitor(REFERENCE, eligibilityId, visitorInserted)
      .then(function () {
        return visitorHelper.get(REFERENCE)
      })
      .then(function (visitor) {
        expect(visitor.EligibilityId).to.equal(eligibilityId)
        expect(visitor.Reference).to.equal(REFERENCE)
        expect(visitor.FirstName).to.equal(visitorHelper.FIRST_NAME)
        expect(visitor.LastName).to.equal(visitorHelper.LAST_NAME)
        expect(visitor.NationalInsuranceNumber).to.equal(visitorHelper.NATIONAL_INSURANCE_NUMBER)
        expect(visitor.DateOfBirth).to.deep.equal(visitorInserted.dob.toDate())
        expect(visitor.PostCode).to.equal(visitorHelper.POST_CODE)
        expect(visitor.Benefit).to.equal(visitorHelper.BENEFIT)
        expect(visitor.BenefitOwner.to.equal(visitorHelper.BENEFITOWNER))
      })
      .then(function () {
        return visitorHelper.delete(REFERENCE)
      })
  })

  it('should throw an error if passed a non visitor object.', function () {
    return expect(function () {
      insertVisitor(REFERENCE, {})
    }).to.throw(Error)
  })

  it('should handle daylight saving time when storing Visitor DOB', function () {
    var dateExpected = dateFormatter.buildFromDateString('1990-10-12')
    var visitorInserted = visitorHelper.build()
    visitorInserted.dob = dateExpected

    return insertVisitor(REFERENCE, eligibilityId, visitorInserted)
      .then(function () {
        return visitorHelper.get(REFERENCE)
      })
      .then(function (visitor) {
        expect(visitor.DateOfBirth).to.deep.equal(dateExpected.toDate())
      })
  })

  after(function () {
    return eligiblityHelper.deleteAll(REFERENCE)
  })
})
<commit_msg>fixing integration tests<commit_after>const expect = require('chai').expect
const eligiblityHelper = require('../../../helpers/data/eligibility-helper')
const visitorHelper = require('../../../helpers/data/visitor-helper')
const insertVisitor = require('../../../../app/services/data/insert-visitor')
const dateFormatter = require('../../../../app/services/date-formatter')

describe('services/data/insert-visitor', function () {
  var REFERENCE = 'V123456'
  var eligibilityId

  before(function () {
    return eligiblityHelper.insert(REFERENCE)
      .then(function (newEligibilityId) {
        eligibilityId = newEligibilityId
      })
  })

  it('should insert a new Visitor for a reference', function () {
    var visitorInserted = visitorHelper.build()
    return insertVisitor(REFERENCE, eligibilityId, visitorInserted)
      .then(function () {
        return visitorHelper.get(REFERENCE)
      })
      .then(function (visitor) {
        expect(visitor.EligibilityId).to.equal(eligibilityId)
        expect(visitor.Reference).to.equal(REFERENCE)
        expect(visitor.FirstName).to.equal(visitorHelper.FIRST_NAME)
        expect(visitor.LastName).to.equal(visitorHelper.LAST_NAME)
        expect(visitor.NationalInsuranceNumber).to.equal(visitorHelper.NATIONAL_INSURANCE_NUMBER)
        expect(visitor.DateOfBirth).to.deep.equal(visitorInserted.dob.toDate())
        expect(visitor.PostCode).to.equal(visitorHelper.POST_CODE)
        expect(visitor.Benefit).to.equal(visitorHelper.BENEFIT)
        expect(visitor.BenefitOwner).to.equal(visitorHelper.BENEFIT_OWNER)
      })
      .then(function () {
        return visitorHelper.delete(REFERENCE)
      })
  })

  it('should throw an error if passed a non visitor object.', function () {
    return expect(function () {
      insertVisitor(REFERENCE, {})
    }).to.throw(Error)
  })

  it('should handle daylight saving time when storing Visitor DOB', function () {
    var dateExpected = dateFormatter.buildFromDateString('1990-10-12')
    var visitorInserted = visitorHelper.build()
    visitorInserted.dob = dateExpected

    return insertVisitor(REFERENCE, eligibilityId, visitorInserted)
      .then(function () {
        return visitorHelper.get(REFERENCE)
      })
      .then(function (visitor) {
        expect(visitor.DateOfBirth).to.deep.equal(dateExpected.toDate())
      })
  })

  after(function () {
    return eligiblityHelper.deleteAll(REFERENCE)
  })
})
<|endoftext|>


<commit_before>describe( 'AngularWizard', function() {
    var $compile, $q, $rootScope, $timeout, WizardHandler;

    beforeEach(module('mgo-angular-wizard'));

    beforeEach(inject(function(_$compile_, _$q_, _$rootScope_, _$timeout_, _WizardHandler_) {
        $compile = _$compile_;
        $q = _$q_;
        $rootScope = _$rootScope_;
        $timeout = _$timeout_;
        WizardHandler = _WizardHandler_;
    }));

    /**
     * Create the view with wizard to test
     * @param  {Scope} scope         A scope to bind to
     * @return {[DOM element]}       A DOM element compiled
     */
    function createView(scope) {
        scope.referenceCurrentStep = null;
        var element = angular.element('<wizard on-finish="finishedWizard()" current-step="referenceCurrentStep" ng-init="msg = 14" >'
                + '    <wz-step wz-title="Starting" canenter="enterValidation">'
                + '
This is the first step
'
                + '
Here you can use whatever you want. You can use other directives, binding, etc.
'
                + '        <input type="submit" wz-next value="Continue" />'
                + '    </wz-step>'
                + '    <wz-step wz-title="Dynamic" wz-disabled="{{dynamicStepDisabled == \'Y\'}}">'
                + '
Dynamic {{dynamicStepDisabled}}
'
                + '
You have continued here!
'
                + '        <input type="submit" wz-next value="Go on" />'
                + '    </wz-step>'
                + '    <wz-step wz-title="Continuing" canexit="stepValidation">'
                + '
Continuing
'
                + '
You have continued here!
'
                + '        <input type="submit" wz-next value="Go on" />'
                + '    </wz-step>'
                + '    <wz-step wz-title="More steps" canenter="enterValidation">'
                + '
Even more steps!!
'
                + '        <input type="submit" wz-next value="Finish now" />'
                + '    </wz-step>'
                + '</wizard>');
        var elementCompiled = $compile(element)(scope);
        $rootScope.$digest();
        return elementCompiled;
    }

    it("should correctly create the wizard", function() {
        var scope = $rootScope.$new();
        var view = createView(scope);
        expect(WizardHandler).toBeTruthy();
        expect(view.find('section').length).toEqual(4);
        // expect the correct step to be desirable one
        expect(scope.referenceCurrentStep).toEqual('Starting');
    });
    it( "should go to the next step", function() {
        var scope = $rootScope.$new();
        var view = createView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Dynamic');
    });
    it( "should render only those steps which are enabled", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
    });
    it( "should enable or disable dynamic steps based on conditions", function() {
        var scope = $rootScope.$new();
        var view = createView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        scope.dynamicStepDisabled = 'Y';
        $rootScope.$digest();
        WizardHandler.wizard().goTo(2);
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('More steps');
    });
    it( "should return to a previous step", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().previous();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Starting');
    });
    it( "should go to a step specified by name", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().goTo('More steps');
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('More steps');
    });
    it( "should go to a step specified by index", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().goTo(2);
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('More steps');
    });
    it( "should go to next step becasue callback is truthy", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next(function(){
            return true
        });
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
    });
    it( "should NOT go to next step because callback is falsey", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next(function(){
            return false
        });
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Starting');
    });
    it( "should go to next step because CANEXIT is UNDEFINED", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
    });
    it( "should go to next step because CANEXIT is TRUE", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createView(scope);
        scope.stepValidation = function(){
            return true;
        };
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('More steps');
    });
    it( "should NOT go to next step because CANEXIT is FALSE", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createView(scope);
        scope.stepValidation = function(){
            return false;
        };
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
    });
    it( "should go to next step because CANENTER is TRUE", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createView(scope);
        scope.enterValidation = function(){
            return true;
        };
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('More steps');
    });
    it( "should NOT go to next step because CANENTER is FALSE", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createView(scope);
        scope.enterValidation = function(){
            return false;
        };
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
    });
    it( "should NOT return to a previous step. Although CANEXIT is false and we are heading to a previous state, the can enter validation is false", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createView(scope);
        scope.stepValidation = function(){
            return false;
        };
        scope.enterValidation = function(){
            return false;
        };
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().previous();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
    });
    it( "should return to a previous step even though CANEXIT is false", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createView(scope);
        scope.stepValidation = function(){
            return false;
        };
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().previous();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Starting');
    });
    it( "should go to the next step because the promise that CANENTER returns resolves to true", function(done) {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createView(scope);
        scope.enterValidation = function(){
            var deferred = $q.defer();
            $timeout(function () {
                deferred.resolve(true);
                done();
            });
            return deferred.promise;
        };
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().next();
        $timeout.flush();
        expect(scope.referenceCurrentStep).toEqual('More steps');
    });
    it( "should go to the next step because CANEXIT is set to true", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createView(scope);
        scope.exitValidation = true;
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('More steps');
    });
    it( "should finish", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var flag = false;
        scope.finishedWizard = function() { flag = true; };
        var view = createView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().finish();
        expect(flag).toBeTruthy();
        $rootScope.$digest();
    });
});
<commit_msg>adding tests for new features<commit_after>describe( 'AngularWizard', function() {
    var $compile, $q, $rootScope, $timeout, WizardHandler;

    beforeEach(module('mgo-angular-wizard'));

    beforeEach(inject(function(_$compile_, _$q_, _$rootScope_, _$timeout_, _WizardHandler_) {
        $compile = _$compile_;
        $q = _$q_;
        $rootScope = _$rootScope_;
        $timeout = _$timeout_;
        WizardHandler = _WizardHandler_;
    }));

    /**
     * Create the generic view with wizard to test
     * @param  {Scope} scope         A scope to bind to
     * @return {[DOM element]}       A DOM element compiled
     */
    function createGenericView(scope) {
        scope.referenceCurrentStep = null;
        var element = angular.element('<wizard on-finish="finishedWizard()" current-step="referenceCurrentStep" ng-init="msg = 14" >'
                + '    <wz-step wz-title="Starting" canenter="enterValidation" description="Step description">'
                + '
This is the first step
'
                + '
Here you can use whatever you want. You can use other directives, binding, etc.
'
                + '        <input type="submit" wz-next value="Continue" />'
                + '    </wz-step>'
                + '    <wz-step wz-title="Dynamic" wz-disabled="{{dynamicStepDisabled == \'Y\'}}">'
                + '
Dynamic {{dynamicStepDisabled}}
'
                + '
You have continued here!
'
                + '        <input type="submit" wz-next value="Go on" />'
                + '    </wz-step>'
                + '    <wz-step wz-title="Continuing" canexit="stepValidation">'
                + '
Continuing
'
                + '
You have continued here!
'
                + '        <input type="submit" wz-next value="Go on" />'
                + '    </wz-step>'
                + '    <wz-step wz-title="More steps" canenter="enterValidation">'
                + '
Even more steps!!
'
                + '        <input type="submit" wz-next value="Finish now" />'
                + '    </wz-step>'
                + '</wizard>');
        var elementCompiled = $compile(element)(scope);
        $rootScope.$digest();
        return elementCompiled;
    }

    it("should correctly create the wizard", function() {
        var scope = $rootScope.$new();
        var view = createGenericView(scope);
        expect(WizardHandler).toBeTruthy();
        expect(view.find('section').length).toEqual(4);
        // expect the correct step to be desirable one
        expect(scope.referenceCurrentStep).toEqual('Starting');
    });
    it( "should go to the next step", function() {
        var scope = $rootScope.$new();
        var view = createGenericView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Dynamic');
    });
    it( "should render only those steps which are enabled", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createGenericView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
    });
    it( "should enable or disable dynamic steps based on conditions", function() {
        var scope = $rootScope.$new();
        var view = createGenericView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        scope.dynamicStepDisabled = 'Y';
        $rootScope.$digest();
        WizardHandler.wizard().goTo(2);
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('More steps');
    });
    it( "should return to a previous step", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createGenericView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().previous();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Starting');
    });
    it( "should go to a step specified by name", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createGenericView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().goTo('More steps');
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('More steps');
    });
    it( "should go to a step specified by index", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createGenericView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().goTo(2);
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('More steps');
    });
    it( "should go to next step becasue callback is truthy", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createGenericView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next(function(){
            return true
        });
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
    });
    it( "should NOT go to next step because callback is falsey", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createGenericView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next(function(){
            return false
        });
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Starting');
    });
    it( "should go to next step because CANEXIT is UNDEFINED", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createGenericView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
    });
    it( "should go to next step because CANEXIT is TRUE", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createGenericView(scope);
        scope.stepValidation = function(){
            return true;
        };
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('More steps');
    });
    it( "should NOT go to next step because CANEXIT is FALSE", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createGenericView(scope);
        scope.stepValidation = function(){
            return false;
        };
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
    });
    it( "should go to next step because CANENTER is TRUE", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createGenericView(scope);
        scope.enterValidation = function(){
            return true;
        };
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('More steps');
    });
    it( "should NOT go to next step because CANENTER is FALSE", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createGenericView(scope);
        scope.enterValidation = function(){
            return false;
        };
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
    });
    it( "should NOT return to a previous step. Although CANEXIT is false and we are heading to a previous state, the can enter validation is false", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createGenericView(scope);
        scope.stepValidation = function(){
            return false;
        };
        scope.enterValidation = function(){
            return false;
        };
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().previous();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
    });
    it( "should return to a previous step even though CANEXIT is false", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createGenericView(scope);
        scope.stepValidation = function(){
            return false;
        };
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().previous();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Starting');
    });
    it( "should go to the next step because the promise that CANENTER returns resolves to true", function(done) {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createGenericView(scope);
        scope.enterValidation = function(){
            var deferred = $q.defer();
            $timeout(function () {
                deferred.resolve(true);
                done();
            });
            return deferred.promise;
        };
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().next();
        $timeout.flush();
        expect(scope.referenceCurrentStep).toEqual('More steps');
    });
    it( "should go to the next step because CANEXIT is set to true", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createGenericView(scope);
        scope.exitValidation = true;
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Continuing');
        WizardHandler.wizard().next();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('More steps');
    });
    it( "should finish", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var flag = false;
        scope.finishedWizard = function() { flag = true; };
        var view = createGenericView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().finish();
        expect(flag).toBeTruthy();
        $rootScope.$digest();
    });
    it( "should go to first step when reset is called", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createGenericView(scope);
        expect(scope.referenceCurrentStep).toEqual('Starting');
        WizardHandler.wizard().goTo(2);
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('More steps');
        WizardHandler.wizard().reset();
        $rootScope.$digest();
        expect(scope.referenceCurrentStep).toEqual('Starting');
    });
    it( "step description should be accessible", function() {
        var scope = $rootScope.$new();
        scope.dynamicStepDisabled = 'Y';
        var view = createGenericView(scope);
        expect(view.isolateScope().steps[0].description).toEqual('Step description');
    });
});
<|endoftext|>


<commit_before>//# sourceURL=rServeService.js

window.smartRApp.factory('rServeService', ['smartRUtils', '$q', '$http', function(smartRUtils, $q, $http) {

    var service = {};

    var NOOP_ABORT = function() {};
    var TIMEOUT = 10000 /* 10 s */;
    var CHECK_DELAY = 1000;
    var SESSION_TOUCH_DELAY = 9 * 60 * 1000; /* 9 min; session timeout is 10 */

    /* we only support one session at a time */

    var state = {
        currentRequestAbort: NOOP_ABORT,
        sessionId: null,
        touchTimeout: null // for current session id
    };

    var workflow = '';
    /* returns a promise with the session id and
     * saves the session id for future calls */
    service.startSession = function(name) {
        workflow = name;
        return $http({
            url: pageInfo.basePath + '/RSession/create',
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            config: {
                timeout: TIMEOUT
            },
            data: {
                workflow: workflow
            }
        })
            .then(function(response) {
                state.sessionId = response.data.sessionId;
                rServeService_scheduleTouch();
            }, transformAjaxFailure);

    };

    service.touch = function(sessionId) {
        if (sessionId != state.sessionId) {
            return;
        }

        return $http({
            url: pageInfo.basePath + '/RSession/touch',
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            config: {
                timeout: TIMEOUT
            },
            data: {
                sessionId: sessionId
            }
        })
            .finally(function() {
                rServeService_scheduleTouch(); // schedule another
            })
    };

    function rServeService_scheduleTouch() {
        var sessionId = state.sessionId;
        window.clearTimeout(state.touchTimeout);
        state.touchTimeout = window.setTimeout(function() {
            service.touch(sessionId);
        }, SESSION_TOUCH_DELAY);
    }

    service.destroySession = function(sessionId) {
        sessionId = sessionId || state.sessionId;

        if (!sessionId) {
            return;
        }

        return $http({
            url: pageInfo.basePath + '/RSession/delete',
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            config: {
                timeout: TIMEOUT
            },
            data: {
                sessionId: sessionId
            }
        })
            .catch(transformAjaxFailure)
            .finally(function() {
                if (state.sessionId == sessionId) {
                    service.abandonCurrentSession();
                }
            });
    };

    service.abandonCurrentSession = function() {
        window.clearTimeout(state.touchTimeout);
        state.sessionId = null;
    };

    service.destroyAndStartSession = function(workflowName) {

        // delete session before creating a new one
        $q.when(service.destroySession())
            .then(function() {
                // start a new session
                service.startSession(workflowName);
            });

    };

    /*
     * taskData = {
     *     arguments: { ... },
     *     taskType: 'fetchData' or name of R script minus .R,
     *     phase: 'fetch' | 'preprocess' | 'run',
     * }
     *
     * If it succeeds, the result will be the data returned by the server.
     * If it fails, it will return an object with at least these fields:
     * {
     *   status: 0 | <http error code>,
     *   statusText: <a description of the error>,
     * }
     */
    service.startScriptExecution = function(taskDataOrig) {

        var taskData = $.extend({}, taskDataOrig); // clone the thing
        state.currentRequestAbort();

        var runRequest = $http({
            url: pageInfo.basePath + '/ScriptExecution/run',
            method: 'POST',
            timeout: TIMEOUT,
            responseType: 'json',
            data: JSON.stringify({
                sessionId: state.sessionId,
                arguments: taskData.arguments,
                taskType: taskData.taskType,
                workflow: workflow
            })
        });

        _setCancellationForAjaxCall(runRequest);

        /* schedule checks */
        var promise = runRequest.then(
            function(response) {
                taskData.executionId = response.data.executionId;
                return _checkStatus(taskData.executionId, CHECK_DELAY);
            },
            transformAjaxFailure
        );

        promise.cancel = function timeoutRequest_cancel() {
            // calling this method should by itself resolve the promise
            state.currentRequestAbort();
        };

        // no touching necessary when a task is running
        window.clearTimeout(state.touchTimeout);
        promise.finally(rServeService_scheduleTouch.bind(this));

        return promise;
    };

    function _setCancellationForAjaxCall(ajax) {
        /* request in-flight; aborting is cancelling this request */
        state.currentRequestAbort = function() { ajax.abort(); };
        /* once the request finishes, there's nothing to abort.
         * this needs to be the 1st callback, so that later callbacks can
         * override this */
        ajax.finally(function() {
            state.currentRequestAbort = NOOP_ABORT;
        });
    }

    /* set a function to be executed after a period of time and
     * simultaneously define the request cancellation function
     * as the cancellation of this timeout.
     * Return the result as a promise. */
    function _setStatusRequestTimeout(funcToCall, delay /*, ... */) {
        var defer = $.Deferred();
        var promise = defer.promise();
        var restOfArguments = Array.prototype.slice.call(arguments)
            .splice(2); // arguments after delay

        function _setStatusRequestTimeout_wrappedFunc() {
            // we cannot abort by calling clearTimeout() anymore
            // funcToCall will probably set its own abort method
            state.currentRequestAbort = NOOP_ABORT;

            // funcToCall should itself return a promise or a final result
            // but let's cover the case where it throws
            var result;
            try {
                result = funcToCall.apply(undefined, restOfArguments); // promise
                result.done(function(x) { defer.resolve(x); });
                result.fail(function(x) { defer.reject(x); });
            } catch (e) {
                defer.fail(e);
            }
        }

        var timeout = window.setTimeout(
            _setStatusRequestTimeout_wrappedFunc, delay);

        state.currentRequestAbort = function() {
            clearTimeout(timeout);
            if (defer.state() == 'pending') {
                defer.reject({
                    status: 0,
                    statusText: 'abort'
                });
            }
            state.currentRequestAbort = NOOP_ABORT;
        };

        return promise;
    }

    /* aux function of _startScriptExecution. Needs to follow its contract
     * with respect to the fail and success result of the promise */
    function _checkStatus(executionId, delay) {
        var ajax = $.ajax({
            type: 'GET',
            url : pageInfo.basePath + '/ScriptExecution/status',
            data: {
                sessionId  : state.sessionId,
                executionId: executionId
            }
        });

        state.currentRequestAbort = function() { ajax.abort(); };
        ajax.always(function() { state.currentRequestAbort = NOOP_ABORT; });

        return ajax.then(function (d) {
            if (d.state === 'FINISHED') {
                d.executionId = executionId;
                return d;
            } else if (d.state === 'FAILED') {
                return $.Deferred().reject({
                    status: 0,
                    statusText: d.result.exception
                }).promise();
            } else {
                // else still pending
                return _setStatusRequestTimeout(
                    _checkStatus, delay, executionId, delay);
            }
        }, transformAjaxFailure);
    }

    function transformAjaxFailure(response) {
        var ret = {
            status: response.status,
            statusText: response.statusText
        };
        if (response.data !== undefined) {
            ret.response = response.data;
        }

        return ret;
    }

    service.downloadJsonFile = function(executionId, filename) {
        // Simple GET request example:
        return $http({
            method: 'GET',
            url: this.urlForFile(executionId, filename)
        });
    };

    service.urlForFile = function(executionId, filename) {
        return pageInfo.basePath +
            '/ScriptExecution/downloadFile?sessionId=' +
            state.sessionId +
            '&executionId=' +
            executionId +
            '&filename=' +
            filename;
    };

    service.loadDataIntoSession = function(conceptKeys, dataConstraints) {
        return $q( function(resolve, reject) {
            smartRUtils.getSubsetIds().then(
                function(subsets) {
                    var _arg = {
                        conceptKeys: conceptKeys,
                        resultInstanceIds: subsets,
                        projection:'log_intensity'
                    };

                    if (typeof dataConstraints !== 'undefined') {
                        _arg.dataConstraints = dataConstraints;
                    }

                    service.startScriptExecution({
                        taskType: 'fetchData',
                        arguments: _arg
                    }).then(
                        function(ret) { resolve('Task complete! State: ' + ret.state); },
                        function(ret) { reject(ret.response); }
                    );
                },
                function() {
                    reject('Could not create subsets. Did you select a cohort?');
                }
            );
        });
    };

    service.executeSummaryStats = function(phase) {
        return $q( function(resolve, reject) {
            service.startScriptExecution({
                taskType: 'summary',
                arguments: {
                    phase: phase,
                    projection: 'log_intensity' // always required, even for low-dim data
                }
            }).then(
                function(ret) {
                    var _result = {};
                    if (ret.result.artifacts.files.length > 0) {
                        service.composeSummaryResults(ret.result.artifacts.files, ret.executionId, phase)
                            .then(function (result) {
                                _result = result;
                                resolve({result : _result, msg:'Task complete! State: ' + ret.state});
                            });
                    } else {
                        resolve({result : _result, msg:'Task complete! State: ' + ret.state});
                    }
                },
                function(ret) { reject(ret.response); }
            );
        });
    };

    service.composeSummaryResults = function(files, executionId, phase) {
        return $q(function (resolve, reject) {
            var retObj = {summary : [], allSamples : 0},
                fileExt = {fetch : ['.png', 'json'], preprocess :['all.png', 'all.json']},

                // find matched items in an array by key
                _find = function composeSummaryResults_find (key, array) {
                    // The variable results needs var in this case (without 'var' a global variable is created)
                    var results = [];
                    for (var i = 0; i < array.length; i++) {
                        if (array[i].search(key) > -1) {
                            results.push(array[i]);
                        }
                    }
                    return results;
                },

                // process each item
                _processItem  = function composeSummaryResults_processItem(img, json) {
                    return $q(function (resolve, reject) {
                        service.downloadJsonFile(executionId, json).then(
                            function (d) {
                                retObj.subsets = d.data.length;
                                d.data.forEach(function (subset) {
                                    retObj.allSamples += subset.numberOfSamples;
                                });
                                resolve({img: service.urlForFile(executionId, img), json:d})
                            },
                            function (err) {reject(err);}
                        );
                    });
                };

            // first identify image and json files
            var _images = _find(fileExt[phase][0], files),
                _jsons = _find(fileExt[phase][1], files);

            // load each json file contents
            for (var i = 0; i < _images.length; i++){
                retObj.summary.push(_processItem(_images[i], _jsons[i]));
            }

            $.when.apply($, retObj.summary).then(function () {
                resolve(retObj); // when all contents has been loaded
            });
        });
    };

    service.preprocess = function(args) {
        return $q(function (resolve, reject) {
            service.startScriptExecution({
                taskType: 'preprocess',
                arguments: args
            }).then(
                function(ret) { resolve('Task complete! State: ' + ret.state); },
                function(ret) { reject(ret.response); }
            );
        });
    };

    return service;
}]);
<commit_msg>forgot to commit this file...<commit_after>//# sourceURL=rServeService.js

window.smartRApp.factory('rServeService', ['smartRUtils', '$q', '$http', function(smartRUtils, $q, $http) {

    var service = {};

    var NOOP_ABORT = function() {};
    var TIMEOUT = 10000 /* 10 s */;
    var CHECK_DELAY = 1000;
    var SESSION_TOUCH_DELAY = 9 * 60 * 1000; /* 9 min; session timeout is 10 */

    /* we only support one session at a time */

    var state = {
        currentRequestAbort: NOOP_ABORT,
        sessionId: null,
        touchTimeout: null // for current session id
    };

    var workflow = '';
    /* returns a promise with the session id and
     * saves the session id for future calls */
    service.startSession = function(name) {
        workflow = name;
        return $http({
            url: pageInfo.basePath + '/RSession/create',
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            config: {
                timeout: TIMEOUT
            },
            data: {
                workflow: workflow
            }
        })
            .then(function(response) {
                state.sessionId = response.data.sessionId;
                rServeService_scheduleTouch();
            }, transformAjaxFailure);

    };

    service.touch = function(sessionId) {
        if (sessionId != state.sessionId) {
            return;
        }

        return $http({
            url: pageInfo.basePath + '/RSession/touch',
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            config: {
                timeout: TIMEOUT
            },
            data: {
                sessionId: sessionId
            }
        })
            .finally(function() {
                rServeService_scheduleTouch(); // schedule another
            })
    };

    function rServeService_scheduleTouch() {
        var sessionId = state.sessionId;
        window.clearTimeout(state.touchTimeout);
        state.touchTimeout = window.setTimeout(function() {
            service.touch(sessionId);
        }, SESSION_TOUCH_DELAY);
    }

    service.destroySession = function(sessionId) {
        sessionId = sessionId || state.sessionId;

        if (!sessionId) {
            return;
        }

        return $http({
            url: pageInfo.basePath + '/RSession/delete',
            method: 'POST',
            headers: {
                'Content-Type': 'application/json'
            },
            config: {
                timeout: TIMEOUT
            },
            data: {
                sessionId: sessionId
            }
        })
            .catch(transformAjaxFailure)
            .finally(function() {
                if (state.sessionId == sessionId) {
                    service.abandonCurrentSession();
                }
            });
    };

    service.abandonCurrentSession = function() {
        window.clearTimeout(state.touchTimeout);
        state.sessionId = null;
    };

    service.destroyAndStartSession = function(workflowName) {

        // delete session before creating a new one
        $q.when(service.destroySession())
            .then(function() {
                // start a new session
                service.startSession(workflowName);
            });

    };

    /*
     * taskData = {
     *     arguments: { ... },
     *     taskType: 'fetchData' or name of R script minus .R,
     *     phase: 'fetch' | 'preprocess' | 'run',
     * }
     *
     * If it succeeds, the result will be the data returned by the server.
     * If it fails, it will return an object with at least these fields:
     * {
     *   status: 0 | <http error code>,
     *   statusText: <a description of the error>,
     * }
     */
    service.startScriptExecution = function(taskDataOrig) {

        var taskData = $.extend({}, taskDataOrig); // clone the thing
        state.currentRequestAbort();

        var runRequest = $http({
            url: pageInfo.basePath + '/ScriptExecution/run',
            method: 'POST',
            timeout: TIMEOUT,
            responseType: 'json',
            data: JSON.stringify({
                sessionId: state.sessionId,
                arguments: taskData.arguments,
                taskType: taskData.taskType,
                workflow: workflow
            })
        });

        _setCancellationForAjaxCall(runRequest);

        /* schedule checks */
        var promise = runRequest.then(
            function(response) {
                taskData.executionId = response.data.executionId;
                return _checkStatus(taskData.executionId, CHECK_DELAY);
            },
            transformAjaxFailure
        );

        promise.cancel = function timeoutRequest_cancel() {
            // calling this method should by itself resolve the promise
            state.currentRequestAbort();
        };

        // no touching necessary when a task is running
        window.clearTimeout(state.touchTimeout);
        promise.finally(rServeService_scheduleTouch.bind(this));

        return promise;
    };

    function _setCancellationForAjaxCall(ajax) {
        /* request in-flight; aborting is cancelling this request */
        state.currentRequestAbort = function() { ajax.abort(); };
        /* once the request finishes, there's nothing to abort.
         * this needs to be the 1st callback, so that later callbacks can
         * override this */
        ajax.finally(function() {
            state.currentRequestAbort = NOOP_ABORT;
        });
    }

    /* set a function to be executed after a period of time and
     * simultaneously define the request cancellation function
     * as the cancellation of this timeout.
     * Return the result as a promise. */
    function _setStatusRequestTimeout(funcToCall, delay /*, ... */) {
        var defer = $.Deferred();
        var promise = defer.promise();
        var restOfArguments = Array.prototype.slice.call(arguments)
            .splice(2); // arguments after delay

        function _setStatusRequestTimeout_wrappedFunc() {
            // we cannot abort by calling clearTimeout() anymore
            // funcToCall will probably set its own abort method
            state.currentRequestAbort = NOOP_ABORT;

            // funcToCall should itself return a promise or a final result
            // but let's cover the case where it throws
            var result;
            try {
                result = funcToCall.apply(undefined, restOfArguments); // promise
                result.done(function(x) { defer.resolve(x); });
                result.fail(function(x) { defer.reject(x); });
            } catch (e) {
                defer.fail(e);
            }
        }

        var timeout = window.setTimeout(
            _setStatusRequestTimeout_wrappedFunc, delay);

        state.currentRequestAbort = function() {
            clearTimeout(timeout);
            if (defer.state() == 'pending') {
                defer.reject({
                    status: 0,
                    statusText: 'abort'
                });
            }
            state.currentRequestAbort = NOOP_ABORT;
        };

        return promise;
    }

    /* aux function of _startScriptExecution. Needs to follow its contract
     * with respect to the fail and success result of the promise */
    function _checkStatus(executionId, delay) {
        var ajax = $.ajax({
            type: 'GET',
            url : pageInfo.basePath + '/ScriptExecution/status',
            data: {
                sessionId  : state.sessionId,
                executionId: executionId
            }
        });

        state.currentRequestAbort = function() { ajax.abort(); };
        ajax.always(function() { state.currentRequestAbort = NOOP_ABORT; });

        return ajax.then(function (d) {
            if (d.state === 'FINISHED') {
                d.executionId = executionId;
                return d;
            } else if (d.state === 'FAILED') {
                return $.Deferred().reject({
                    status: 0,
                    statusText: d.result.exception
                }).promise();
            } else {
                // else still pending
                return _setStatusRequestTimeout(
                    _checkStatus, delay, executionId, delay);
            }
        }, transformAjaxFailure);
    }

    function transformAjaxFailure(response) {
        var ret = {
            status: response.status,
            statusText: response.statusText
        };
        if (response.data !== undefined) {
            ret.response = response.data;
        }

        return ret;
    }

    service.downloadJsonFile = function(executionId, filename) {
        // Simple GET request example:
        return $http({
            method: 'GET',
            url: this.urlForFile(executionId, filename)
        });
    };

    service.urlForFile = function(executionId, filename) {
        return pageInfo.basePath +
            '/ScriptExecution/downloadFile?sessionId=' +
            state.sessionId +
            '&executionId=' +
            executionId +
            '&filename=' +
            filename;
    };

    service.loadDataIntoSession = function(conceptKeys, dataConstraints) {
        return $q(function(resolve, reject) {
            smartRUtils.getSubsetIds().then(
                function(subsets) {
                    var _arg = {
                        conceptKeys: conceptKeys,
                        resultInstanceIds: subsets,
                        projection:'log_intensity'
                    };

                    if (typeof dataConstraints !== 'undefined') {
                        _arg.dataConstraints = dataConstraints;
                    }

                    service.startScriptExecution({
                        taskType: 'fetchData',
                        arguments: _arg
                    }).then(
                        function(ret) { resolve('Task complete! State: ' + ret.state); },
                        function(ret) { reject(ret.statusText); }
                    );
                },
                function() {
                    reject('Could not create subsets. Did you select a cohort?');
                }
            );
        });
    };

    service.executeSummaryStats = function(phase) {
        return $q( function(resolve, reject) {
            service.startScriptExecution({
                taskType: 'summary',
                arguments: {
                    phase: phase,
                    projection: 'log_intensity' // always required, even for low-dim data
                }
            }).then(
                function(ret) {
                    var _result = {};
                    if (ret.result.artifacts.files.length > 0) {
                        service.composeSummaryResults(ret.result.artifacts.files, ret.executionId, phase)
                            .then(function (result) {
                                _result = result;
                                resolve({result : _result, msg:'Task complete! State: ' + ret.state});
                            });
                    } else {
                        resolve({result : _result, msg:'Task complete! State: ' + ret.state});
                    }
                },
                function(ret) { reject(ret.response); }
            );
        });
    };

    service.composeSummaryResults = function(files, executionId, phase) {
        return $q(function (resolve, reject) {
            var retObj = {summary : [], allSamples : 0},
                fileExt = {fetch : ['.png', 'json'], preprocess :['all.png', 'all.json']},

                // find matched items in an array by key
                _find = function composeSummaryResults_find (key, array) {
                    // The variable results needs var in this case (without 'var' a global variable is created)
                    var results = [];
                    for (var i = 0; i < array.length; i++) {
                        if (array[i].search(key) > -1) {
                            results.push(array[i]);
                        }
                    }
                    return results;
                },

                // process each item
                _processItem  = function composeSummaryResults_processItem(img, json) {
                    return $q(function (resolve, reject) {
                        service.downloadJsonFile(executionId, json).then(
                            function (d) {
                                retObj.subsets = d.data.length;
                                d.data.forEach(function (subset) {
                                    retObj.allSamples += subset.numberOfSamples;
                                });
                                resolve({img: service.urlForFile(executionId, img), json:d})
                            },
                            function (err) {reject(err);}
                        );
                    });
                };

            // first identify image and json files
            var _images = _find(fileExt[phase][0], files),
                _jsons = _find(fileExt[phase][1], files);

            // load each json file contents
            for (var i = 0; i < _images.length; i++){
                retObj.summary.push(_processItem(_images[i], _jsons[i]));
            }

            $.when.apply($, retObj.summary).then(function () {
                resolve(retObj); // when all contents has been loaded
            });
        });
    };

    service.preprocess = function(args) {
        return $q(function (resolve, reject) {
            service.startScriptExecution({
                taskType: 'preprocess',
                arguments: args
            }).then(
                function(ret) { resolve('Task complete! State: ' + ret.state); },
                function(ret) { reject(ret.response); }
            );
        });
    };

    return service;
}]);
<|endoftext|>