<commit_before>/* -------------------------------------------------------------------------- */
/* Copyright 2010-2012, C12G Labs S.L                                         */
/*                                                                            */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
/* not use this file except in compliance with the License. You may obtain    */
/* a copy of the License at                                                   */
/*                                                                            */
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
/*                                                                            */
/* Unless required by applicable law or agreed to in writing, software        */
/* distributed under the License is distributed on an "AS IS" BASIS,          */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
/* See the License for the specific language governing permissions and        */
/* limitations under the License.                                             */
/* -------------------------------------------------------------------------- */

/* Marketpplace tab plugin */
var dataTable_marketplace;

/*
 * fnReloadAjax: re-read the Ajax source and update the table
 */

$.fn.dataTableExt.oApi.fnReloadAjax = function ( oSettings, sNewSource, fnCallback, bStandingRedraw )
{
    if ( typeof sNewSource != 'undefined' && sNewSource != null )
    {
        oSettings.sAjaxSource = sNewSource;
    }
    this.oApi._fnProcessingDisplay( oSettings, true );
    var that = this;
    var iStart = oSettings._iDisplayStart;
    var aData = [];

    this.oApi._fnServerParams( oSettings, aData );

    oSettings.fnServerData( oSettings.sAjaxSource, aData, function(json) {
        /* Clear the old information from the table */
        that.oApi._fnClearTable( oSettings );

        /* Got the data - add it to the table */
        var aData =  (oSettings.sAjaxDataProp !== "") ?
            that.oApi._fnGetObjectDataFn( oSettings.sAjaxDataProp )( json ) : json;

        for ( var i=0 ; i<aData.length ; i++ )
        {
            that.oApi._fnAddData( oSettings, aData[i] );
        }

        oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
        that.fnDraw();

        if ( typeof bStandingRedraw != 'undefined' && bStandingRedraw === true )
        {
            oSettings._iDisplayStart = iStart;
            that.fnDraw( false );
        }

        that.oApi._fnProcessingDisplay( oSettings, false );

        /* Callback user function - for event handlers etc */
        if ( typeof fnCallback == 'function' && fnCallback != null )
        {
            fnCallback( oSettings );
        }
    }, oSettings );
}

/*
 * MAIN TAB
 */

var market_actions = {
    "Marketplace.refresh" : {
        type: "custom",
        call: function () {
            dataTable_marketplace.fnReloadAjax();
        }
    },
    "Marketplace.import" : {
        type: "single",
        call: function () {
            var app_id = getSelectedNodes(dataTable_marketplace)[0];

            $.ajax({
                url: "/marketplace/" + app_id,
                type: "GET",
                dataType: "json",
                success: function(response){
                    document.getElementById("img_name").value = response['name'];
                    document.getElementById("img_path").value = response['links']['download']['href'];
                    popUpCreateImageDialog();
                },
                error: function(response)
                {
                    return onError(null, OpenNebula.Error(response));
                }
            });
        }
    }
}

var market_buttons = {
    "Marketplace.refresh" : {
        type: "image",
        text: tr("Refresh list"),
        img: "images/Refresh-icon.png"
    },
    "Marketplace.import" : {
        type: "action",
        text: tr('Import to local infrastructure')
    }
};

var marketplace_tab_content = '\

'+tr("OpenNebula Marketplace")+'
\
<form id="marketplace_form" action="" action="javascript:alert(\'js error!\');">\

\

\

\

\

\
      	\
      '+tr("ID")+'	\
      '+tr("Name")+'	\
      '+tr("Publisher")+'	\
      '+tr("Hypervisor")+'	\
      '+tr("Arch")+'	\
      '+tr("Format")+'	\
      '+tr("Tags")+'	\

\

\

\

\

\

';

var marketplace_tab = {
    title: '' + tr("Marketplace"),
    content: marketplace_tab_content,
    buttons: market_buttons,
};

Sunstone.addMainTab('marketplace_tab', marketplace_tab);
Sunstone.addActions(market_actions);

/*
 * INFO PANEL
 */

var marketplace_info_panel = {
    "marketplace_info_tab" : {
        title: tr("Appliance information"),
        content:""
    },
};

Sunstone.addInfoPanel("marketplace_info_panel", marketplace_info_panel);

function updateMarketInfo(request,app){
    var info_tab = {
        title : tr("Appliance information"),
        content :
        '
\

\

'+tr("Appliance information")+'
\

\

\

\
                ' + tr("ID") + '	\
                '+app['_id']["$oid"]+'	\

\

\
                ' + tr("Publisher") + '	\
                '+app['publisher']+'	\

\

\
                ' + tr("Downloads") + '	\
                '+app['downloads']+'	\

\

\
                ' + tr("OS") + '	\
                '+app['files'][0]['os-id']+' '+app['files'][0]['os-release']+'	\

\

\
                ' + tr("Arch") + '	\
                '+app['files'][0]['os-arch']+'	\

\

\
                ' + tr("Size") + '	\
                '+app['files'][0]['size']+'	\

\

\
                ' + tr("Hypervisor") + '	\
                '+app['files'][0]['hypervisor']+'	\

\

\

\

\

\

'+tr("Description")+'
\

\

\

\
                '+app['description'].replace(/\n/g, "
")+'	\

\

\

'
    };

    Sunstone.updateInfoPanelTab("marketplace_info_panel", "marketplace_info_tab", info_tab);
    Sunstone.popUpInfoPanel("marketplace_info_panel");
};

function infoListenerMarket(dataTable){
    $('tbody tr',dataTable).live("click",function(e){
        if ($(e.target).is('input')) {return true;}

        var aData = dataTable.fnGetData(this);
        var id = aData["_id"]["$oid"];
        if (!id) return true;

        popDialogLoading();

        $.ajax({
            url: "/marketplace/" + id,
            type: "GET",
            dataType: "json",
            success: function(response){
                return updateMarketInfo(null, response);
            },
            error: function(response)
            {
                return onError(null, OpenNebula.Error(response));
            }
        });

        return false;
    });
}

/*
 * onlyOneCheckboxListener: Only one box can be checked
 */

function onlyOneCheckboxListener(dataTable) {
    $('tbody input.check_item', dataTable).live("change", function(){
        var checked = $('input.check_item:checked', $('tr', dataTable));
        var self = this;
        checked.each(function(){
          if(this!=self) this.checked = ''
        })
    });
}

/*
 * Document
 */

$(document).ready(function(){
    dataTable_marketplace = $("#datatable_marketplace", main_tabs_context).dataTable({
        "bJQueryUI": true,
        "bSortClasses": false,
        "sPaginationType": "full_numbers",
        "sDom" : '<"H"lfrC>t<"F"ip>',
        "sAjaxSource": "/marketplace",
        "sAjaxDataProp": "appliances",
        "bAutoWidth":false,
        "aoColumns": [
            { "bSortable": false,
              "fnRender": function ( o, val ) {
                  return '<input class="check_item" type="checkbox" id="marketplace_'+o.aData['_id']['$oid']+'" name="selected_items" value="'+o.aData['_id']['$oid']+'"/>'
            } },
            { "mDataProp": "_id.$oid", "bVisible": false },
            { "mDataProp": "name" },
            { "mDataProp": "publisher" },
            { "mDataProp": "files.0.hypervisor"},
            { "mDataProp": "files.0.os-arch"},
            { "mDataProp": "files.0.format"},
            { "mDataProp": "tags", "bVisible": false}
          ],
        "oLanguage": (datatable_lang != "") ?
            {
                sUrl: "locale/"+lang+"/"+datatable_lang
            } : ""
    });

    initCheckAllBoxes(dataTable_marketplace);
    tableCheckboxesListener(dataTable_marketplace);
    onlyOneCheckboxListener(dataTable_marketplace);

    infoListenerMarket(dataTable_marketplace);
});<commit_msg>feature #1303: Add checksum support to marketplace tab<commit_after>/* -------------------------------------------------------------------------- */
/* Copyright 2010-2012, C12G Labs S.L                                         */
/*                                                                            */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may    */
/* not use this file except in compliance with the License. You may obtain    */
/* a copy of the License at                                                   */
/*                                                                            */
/* http://www.apache.org/licenses/LICENSE-2.0                                 */
/*                                                                            */
/* Unless required by applicable law or agreed to in writing, software        */
/* distributed under the License is distributed on an "AS IS" BASIS,          */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   */
/* See the License for the specific language governing permissions and        */
/* limitations under the License.                                             */
/* -------------------------------------------------------------------------- */

/* Marketpplace tab plugin */
var dataTable_marketplace;

/*
 * fnReloadAjax: re-read the Ajax source and update the table
 */

$.fn.dataTableExt.oApi.fnReloadAjax = function ( oSettings, sNewSource, fnCallback, bStandingRedraw )
{
    if ( typeof sNewSource != 'undefined' && sNewSource != null )
    {
        oSettings.sAjaxSource = sNewSource;
    }
    this.oApi._fnProcessingDisplay( oSettings, true );
    var that = this;
    var iStart = oSettings._iDisplayStart;
    var aData = [];

    this.oApi._fnServerParams( oSettings, aData );

    oSettings.fnServerData( oSettings.sAjaxSource, aData, function(json) {
        /* Clear the old information from the table */
        that.oApi._fnClearTable( oSettings );

        /* Got the data - add it to the table */
        var aData =  (oSettings.sAjaxDataProp !== "") ?
            that.oApi._fnGetObjectDataFn( oSettings.sAjaxDataProp )( json ) : json;

        for ( var i=0 ; i<aData.length ; i++ )
        {
            that.oApi._fnAddData( oSettings, aData[i] );
        }

        oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
        that.fnDraw();

        if ( typeof bStandingRedraw != 'undefined' && bStandingRedraw === true )
        {
            oSettings._iDisplayStart = iStart;
            that.fnDraw( false );
        }

        that.oApi._fnProcessingDisplay( oSettings, false );

        /* Callback user function - for event handlers etc */
        if ( typeof fnCallback == 'function' && fnCallback != null )
        {
            fnCallback( oSettings );
        }
    }, oSettings );
}

/*
 * MAIN TAB
 */

var market_actions = {
    "Marketplace.refresh" : {
        type: "custom",
        call: function () {
            dataTable_marketplace.fnReloadAjax();
        }
    },
    "Marketplace.import" : {
        type: "single",
        call: function () {
            var app_id = getSelectedNodes(dataTable_marketplace)[0];

            $.ajax({
                url: "/marketplace/" + app_id,
                type: "GET",
                dataType: "json",
                success: function(response){
                    document.getElementById("img_name").value = response['name'];
                    document.getElementById("img_path").value = response['links']['download']['href'];

                    var md5 = response['files'][0]['checksum']['md5']
                    if ( md5 ) {
                        option = '<option value=\''+md5+'\' name="MD5">MD5='+md5+'</option>';
                        $("#custom_var_image_box").append(option);
                    }

                    var sha1 = response['files'][0]['checksum']['sha1']
                    if ( sha1 ) {
                        option = '<option value=\''+sha1+'\' name="SHA1">SHA1='+sha1+'</option>';
                        $("#custom_var_image_box").append(option);
                    }

                    popUpCreateImageDialog();
                },
                error: function(response)
                {
                    return onError(null, OpenNebula.Error(response));
                }
            });
        }
    }
}

var market_buttons = {
    "Marketplace.refresh" : {
        type: "image",
        text: tr("Refresh list"),
        img: "images/Refresh-icon.png"
    },
    "Marketplace.import" : {
        type: "action",
        text: tr('Import to local infrastructure')
    }
};

var marketplace_tab_content = '\

'+tr("OpenNebula Marketplace")+'
\
<form id="marketplace_form" action="" action="javascript:alert(\'js error!\');">\

\

\

\

\

\
      	\
      '+tr("ID")+'	\
      '+tr("Name")+'	\
      '+tr("Publisher")+'	\
      '+tr("Hypervisor")+'	\
      '+tr("Arch")+'	\
      '+tr("Format")+'	\
      '+tr("Tags")+'	\

\

\

\

\

\

';

var marketplace_tab = {
    title: '' + tr("Marketplace"),
    content: marketplace_tab_content,
    buttons: market_buttons,
};

Sunstone.addMainTab('marketplace_tab', marketplace_tab);
Sunstone.addActions(market_actions);

/*
 * INFO PANEL
 */

var marketplace_info_panel = {
    "marketplace_info_tab" : {
        title: tr("Appliance information"),
        content:""
    },
};

Sunstone.addInfoPanel("marketplace_info_panel", marketplace_info_panel);

function updateMarketInfo(request,app){
    var info_tab = {
        title : tr("Appliance information"),
        content :
        '
\

\

'+tr("Appliance information")+'
\

\

\

\
                ' + tr("ID") + '	\
                '+app['_id']["$oid"]+'	\

\

\
                ' + tr("Publisher") + '	\
                '+app['publisher']+'	\

\

\
                ' + tr("Downloads") + '	\
                '+app['downloads']+'	\

\

\
                ' + tr("OS") + '	\
                '+app['files'][0]['os-id']+' '+app['files'][0]['os-release']+'	\

\

\
                ' + tr("Arch") + '	\
                '+app['files'][0]['os-arch']+'	\

\

\
                ' + tr("Size") + '	\
                '+app['files'][0]['size']+'	\

\

\
                ' + tr("Hypervisor") + '	\
                '+app['files'][0]['hypervisor']+'	\

\

\

\

\

\

'+tr("Description")+'
\

\

\

\
                '+app['description'].replace(/\n/g, "
")+'	\

\

\

'
    };

    Sunstone.updateInfoPanelTab("marketplace_info_panel", "marketplace_info_tab", info_tab);
    Sunstone.popUpInfoPanel("marketplace_info_panel");
};

function infoListenerMarket(dataTable){
    $('tbody tr',dataTable).live("click",function(e){
        if ($(e.target).is('input')) {return true;}

        var aData = dataTable.fnGetData(this);
        var id = aData["_id"]["$oid"];
        if (!id) return true;

        popDialogLoading();

        $.ajax({
            url: "/marketplace/" + id,
            type: "GET",
            dataType: "json",
            success: function(response){
                return updateMarketInfo(null, response);
            },
            error: function(response)
            {
                return onError(null, OpenNebula.Error(response));
            }
        });

        return false;
    });
}

/*
 * onlyOneCheckboxListener: Only one box can be checked
 */

function onlyOneCheckboxListener(dataTable) {
    $('tbody input.check_item', dataTable).live("change", function(){
        var checked = $('input.check_item:checked', $('tr', dataTable));
        var self = this;
        checked.each(function(){
          if(this!=self) this.checked = ''
        })
    });
}

/*
 * Document
 */

$(document).ready(function(){
    dataTable_marketplace = $("#datatable_marketplace", main_tabs_context).dataTable({
        "bJQueryUI": true,
        "bSortClasses": false,
        "sPaginationType": "full_numbers",
        "sDom" : '<"H"lfrC>t<"F"ip>',
        "sAjaxSource": "/marketplace",
        "sAjaxDataProp": "appliances",
        "bAutoWidth":false,
        "aoColumns": [
            { "bSortable": false,
              "fnRender": function ( o, val ) {
                  return '<input class="check_item" type="checkbox" id="marketplace_'+o.aData['_id']['$oid']+'" name="selected_items" value="'+o.aData['_id']['$oid']+'"/>'
            } },
            { "mDataProp": "_id.$oid", "bVisible": false },
            { "mDataProp": "name" },
            { "mDataProp": "publisher" },
            { "mDataProp": "files.0.hypervisor"},
            { "mDataProp": "files.0.os-arch"},
            { "mDataProp": "files.0.format"},
            { "mDataProp": "tags", "bVisible": false}
          ],
        "oLanguage": (datatable_lang != "") ?
            {
                sUrl: "locale/"+lang+"/"+datatable_lang
            } : ""
    });

    initCheckAllBoxes(dataTable_marketplace);
    tableCheckboxesListener(dataTable_marketplace);
    onlyOneCheckboxListener(dataTable_marketplace);

    infoListenerMarket(dataTable_marketplace);
});<|endoftext|>


<commit_before>describe('GDP.LANDING.views.DataSourceSelectionView', function() {
	var getDeferred;
	var templateSpy;
	var collection;
	var testView;

	beforeEach(function() {
		$('body').append('

');
		getDeferred = $.Deferred();
		GDP.cswClient = {
			requestGetRecords : jasmine.createSpy('requestGetRecordsSpy').andReturn(getDeferred.promise())
		};

		GDP.algorithms = {
			get : jasmine.createSpy('algorithmsGetSpy').andReturn({'1234' : ['Alg1', 'Alg2']})
		};
		templateSpy = jasmine.createSpy('templateSpy');
		GDP.LANDING.templates = {
			getTemplate : jasmine.createSpy('getTemplateSpy').andReturn(templateSpy)
		};
		collection = new GDP.models.DataSetCollection();
		spyOn(GDP.LANDING.views.DataSetTileView.prototype, 'initialize');
		spyOn(GDP.LANDING.views.DataSetTileView.prototype, 'setVisibility');

		GDP.logger = {
			debug : jasmine.createSpy('debugSpy')
		};

		GDP.config = {
			get : function(prop) {
				if (prop === 'process') {
					return {
						processes : [
							{
								id : 'ALG1',
								name : 'NAME1',
								title : 'TITLE1',
								type : 'TYPE1'
							},
							{
								id : 'ALG2',
								name : 'NAME2',
								title : 'TITLE2',
								type : 'TYPE1'
							},
							{
								id : 'ALG3',
								name : 'NAME3',
								title : 'TITLE3',
								type : 'TYPE2'
							}
						]
					};
				}
				else {
					return null;
				}
			}
		};

		testView = new GDP.LANDING.views.DataSourceSelectionView({
			template : templateSpy,
			collection : collection
		});
	});

	afterEach(function() {
		$('.dataset-tile-container').remove();
	});

	it('Expects that a getRecords request is made', function() {
		expect(GDP.cswClient.requestGetRecords).toHaveBeenCalled();
	});

	it('Expects a successful GetRecords request to create DataSetModels and dataSetViews for each record', function() {
		var response = {
			records : [
				{
					identificationInfo : [
						{ abstract : {CharacterString : {value : 'Abstract1'}},
						citation : {title : {CharacterString : {value : 'Title1'}}}}
					],
					fileIdentifier : {CharacterString : {value :'ID1'}}

				}, {
					identificationInfo : [
						{ abstract : {CharacterString : {value : 'Abstract2'}},
						citation : {title : {CharacterString : {value : 'Title2'}}}}
					],
					fileIdentifier : {CharacterString : {value :'ID2'}}
				}, {
					identificationInfo : [
						{ abstract : {CharacterString : {value : 'Abstract3'}},
						citation : {title : {CharacterString : {value : 'Title3'}}}}
					],
					fileIdentifier : {CharacterString : {value :'ID3'}}
				}
			]
		};
		getDeferred.resolve(response);
		expect(testView.collection.size()).toBe(3);
		expect(testView.collection.first().attributes).toEqual({
			abstrct : 'Abstract1',
			bounds : '',
			identifier : 'ID1',
			algorithms : [],
			title : 'Title1',
			dataSources : [],
			contactInfo : [],
			datasetTimeRange : null,
			distributionInfo : null
		});
		expect(GDP.LANDING.views.DataSetTileView.prototype.initialize.calls.length).toBe(3);
		expect(GDP.LANDING.views.DataSetTileView.prototype.initialize.calls[0].args[0].model).toEqual(testView.collection.first())
		expect(testView.dataSetViews.length).toBe(3);
	});

	it('Expects a failed getRecords call to create no models or views', function() {
		getDeferred.reject('Unavailable');
		expect(testView.collection.size()).toBe(0);
		expect(GDP.LANDING.views.DataSetTileView.prototype.initialize).not.toHaveBeenCalled();
		expect(testView.dataSetViews.length).toBe(0);
	});

	describe('Tests for filterBy* methods', function() {

		beforeEach(function() {
			spyOn(GDP.models.DataSetModel.prototype, 'isInFilter');

			var response = {
				records : [
					{
						identificationInfo : [
							{ abstract : {CharacterString : {value : 'Abstract1'}},
							citation : {title : {CharacterString : {value : 'Title1'}}}}
						],
						fileIdentifier : {CharacterString : {value :'ID1'}}

					}, {
						identificationInfo : [
							{ abstract : {CharacterString : {value : 'Abstract2'}},
							citation : {title : {CharacterString : {value : 'Title2'}}}}
						],
						fileIdentifier : {CharacterString : {value :'ID2'}}
					}, {
						identificationInfo : [
							{ abstract : {CharacterString : {value : 'Abstract3'}},
							citation : {title : {CharacterString : {value : 'Title3'}}}}
						],
						fileIdentifier : {CharacterString : {value :'ID3'}}
					}
				]
			};
			getDeferred.resolve(response);
		});

		it('Expects a call to filterByText to update the text filter and call isInFilter for each model in the collection', function() {
			testView.filterByText({target : {value : 'This'}});

			expect(GDP.models.DataSetModel.prototype.isInFilter.calls.length).toBe(3);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[0].args[0].text).toEqual('This');
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[1].args[0].text).toEqual('This');
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[2].args[0].text).toEqual('This');

			testView.filterByText({target : {value : ''}});
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls.length).toBe(6);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[3].args[0].text).toEqual('');
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[4].args[0].text).toEqual('');
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[5].args[0].text).toEqual('');
		});

		it('Expects a call to filterByAlgorithm to update the algorithms call and call isInFilter for each model in the collection', function() {
			testView.filterByAlgorithm({target : {checked : true, value : 'TYPE1'}});

			expect(GDP.models.DataSetModel.prototype.isInFilter.calls.length).toBe(3);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[0].args[0].algorithms).toEqual(['ALG1', 'ALG2']);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[1].args[0].algorithms).toEqual(['ALG1', 'ALG2']);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[2].args[0].algorithms).toEqual(['ALG1', 'ALG2']);

			testView.filterByAlgorithm({target : {checked : true, value : 'TYPE2'}});

			expect(GDP.models.DataSetModel.prototype.isInFilter.calls.length).toBe(6);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[3].args[0].algorithms).toEqual(['ALG1', 'ALG2', 'ALG3']);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[4].args[0].algorithms).toEqual(['ALG1', 'ALG2', 'ALG3']);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[5].args[0].algorithms).toEqual(['ALG1', 'ALG2', 'ALG3']);

			testView.filterByAlgorithm({target : {checked : false, value : 'TYPE1'}});
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls.length).toBe(9);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[6].args[0].algorithms).toEqual(['ALG3']);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[7].args[0].algorithms).toEqual(['ALG3']);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[8].args[0].algorithms).toEqual(['ALG3']);
		});

	});

});<commit_msg>Added tests for aoiMessageContext property in DataSourceSelectionView_spec.<commit_after>/*global GDP*/
/*global jasmine*/
/*global expect*/

describe('GDP.LANDING.views.DataSourceSelectionView', function() {
	var getDeferred;
	var templateSpy;
	var collection;
	var testView;

	beforeEach(function() {
		$('body').append('

');
		getDeferred = $.Deferred();
		GDP.cswClient = {
			requestGetRecords : jasmine.createSpy('requestGetRecordsSpy').andReturn(getDeferred.promise())
		};

		GDP.algorithms = {
			get : jasmine.createSpy('algorithmsGetSpy').andReturn({'1234' : ['Alg1', 'Alg2']})
		};
		templateSpy = jasmine.createSpy('templateSpy');
		GDP.LANDING.templates = {
			getTemplate : jasmine.createSpy('getTemplateSpy').andReturn(templateSpy)
		};
		collection = new GDP.models.DataSetCollection();
		spyOn(GDP.LANDING.views.DataSetTileView.prototype, 'initialize');
		spyOn(GDP.LANDING.views.DataSetTileView.prototype, 'setVisibility');

		GDP.logger = {
			debug : jasmine.createSpy('debugSpy')
		};

		GDP.config = {
			get : function(prop) {
				if (prop === 'process') {
					return {
						processes : [
							{
								id : 'ALG1',
								name : 'NAME1',
								title : 'TITLE1',
								type : 'TYPE1'
							},
							{
								id : 'ALG2',
								name : 'NAME2',
								title : 'TITLE2',
								type : 'TYPE1'
							},
							{
								id : 'ALG3',
								name : 'NAME3',
								title : 'TITLE3',
								type : 'TYPE2'
							}
						]
					};
				}
				else {
					return null;
				}
			}
		};

	});

	afterEach(function() {
		$('.dataset-tile-container').remove();
	});

	it('Expects the template to be called with an empty aoiMessageContext property if no incomingParams defined', function() {
		GDP.incomingParams = {};
		testView = new GDP.LANDING.views.DataSourceSelectionView({
			template : templateSpy,
			collection : collection
		});

		expect(templateSpy.calls[0].args[0].aoiMessageContext).toEqual({});
	});

	it('Expects the template to be called with aoiMessageContext property set to an object with a sciencebase property when caller param is sciencebase', function() {
		GDP.incomingParams = {
			caller : 'sciencebase',
			item_id : '1234',
			redirect_url : 'http://www.sciencebase.gov/catalog/gdp/1234'
		};
		testView = new GDP.LANDING.views.DataSourceSelectionView({
			template : templateSpy,
			collection : collection
		});
		expect(templateSpy.calls[0].args[0].aoiMessageContext).toEqual({
			sciencebase : {
				url : 'http://www.sciencebase.gov/catalog/item/1234'
			}
		});
	});

	it('Expects the template to be called with aoimessageContext property set with a default property when called param is not sciencebase', function() {
		GDP.incomingParams = {
			caller : 'otherservice',
			item_id : '1234'
		};
		testView = new GDP.LANDING.views.DataSourceSelectionView({
			template : templateSpy,
			collection : collection
		});
		expect(templateSpy.calls[0].args[0].aoiMessageContext).toEqual({
			default : {
				itemId : '1234',
				caller : 'otherservice'
			}
		});
	});

	describe('Tests for getRecords request processing', function() {
		beforeEach(function() {
			testView = new GDP.LANDING.views.DataSourceSelectionView({
				template : templateSpy,
				collection : collection
			});
		});

		it('Expects that a getRecords request is made', function() {
			expect(GDP.cswClient.requestGetRecords).toHaveBeenCalled();
		});

		it('Expects a successful GetRecords request to create DataSetModels and dataSetViews for each record', function() {
			var response = {
				records : [
					{
						identificationInfo : [
							{ abstract : {CharacterString : {value : 'Abstract1'}},
							citation : {title : {CharacterString : {value : 'Title1'}}}}
						],
						fileIdentifier : {CharacterString : {value :'ID1'}}

					}, {
						identificationInfo : [
							{ abstract : {CharacterString : {value : 'Abstract2'}},
							citation : {title : {CharacterString : {value : 'Title2'}}}}
						],
						fileIdentifier : {CharacterString : {value :'ID2'}}
					}, {
						identificationInfo : [
							{ abstract : {CharacterString : {value : 'Abstract3'}},
							citation : {title : {CharacterString : {value : 'Title3'}}}}
						],
						fileIdentifier : {CharacterString : {value :'ID3'}}
					}
				]
			};
			getDeferred.resolve(response);
			expect(testView.collection.size()).toBe(3);
			expect(testView.collection.first().attributes).toEqual({
				abstrct : 'Abstract1',
				bounds : '',
				identifier : 'ID1',
				algorithms : [],
				title : 'Title1',
				dataSources : [],
				contactInfo : [],
				datasetTimeRange : null,
				distributionInfo : null
			});
			expect(GDP.LANDING.views.DataSetTileView.prototype.initialize.calls.length).toBe(3);
			expect(GDP.LANDING.views.DataSetTileView.prototype.initialize.calls[0].args[0].model).toEqual(testView.collection.first());
			expect(testView.dataSetViews.length).toBe(3);
		});

		it('Expects a failed getRecords call to create no models or views', function() {
			getDeferred.reject('Unavailable');
			expect(testView.collection.size()).toBe(0);
			expect(GDP.LANDING.views.DataSetTileView.prototype.initialize).not.toHaveBeenCalled();
			expect(testView.dataSetViews.length).toBe(0);
		});
	});

	describe('Tests for filterBy* methods', function() {

		beforeEach(function() {
			testView = new GDP.LANDING.views.DataSourceSelectionView({
				template : templateSpy,
				collection : collection
			});

			spyOn(GDP.models.DataSetModel.prototype, 'isInFilter');

			var response = {
				records : [
					{
						identificationInfo : [
							{ abstract : {CharacterString : {value : 'Abstract1'}},
							citation : {title : {CharacterString : {value : 'Title1'}}}}
						],
						fileIdentifier : {CharacterString : {value :'ID1'}}

					}, {
						identificationInfo : [
							{ abstract : {CharacterString : {value : 'Abstract2'}},
							citation : {title : {CharacterString : {value : 'Title2'}}}}
						],
						fileIdentifier : {CharacterString : {value :'ID2'}}
					}, {
						identificationInfo : [
							{ abstract : {CharacterString : {value : 'Abstract3'}},
							citation : {title : {CharacterString : {value : 'Title3'}}}}
						],
						fileIdentifier : {CharacterString : {value :'ID3'}}
					}
				]
			};
			getDeferred.resolve(response);
		});

		it('Expects a call to filterByText to update the text filter and call isInFilter for each model in the collection', function() {
			testView.filterByText({target : {value : 'This'}});

			expect(GDP.models.DataSetModel.prototype.isInFilter.calls.length).toBe(3);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[0].args[0].text).toEqual('This');
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[1].args[0].text).toEqual('This');
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[2].args[0].text).toEqual('This');

			testView.filterByText({target : {value : ''}});
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls.length).toBe(6);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[3].args[0].text).toEqual('');
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[4].args[0].text).toEqual('');
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[5].args[0].text).toEqual('');
		});

		it('Expects a call to filterByAlgorithm to update the algorithms call and call isInFilter for each model in the collection', function() {
			testView.filterByAlgorithm({target : {checked : true, value : 'TYPE1'}});

			expect(GDP.models.DataSetModel.prototype.isInFilter.calls.length).toBe(3);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[0].args[0].algorithms).toEqual(['ALG1', 'ALG2']);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[1].args[0].algorithms).toEqual(['ALG1', 'ALG2']);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[2].args[0].algorithms).toEqual(['ALG1', 'ALG2']);

			testView.filterByAlgorithm({target : {checked : true, value : 'TYPE2'}});

			expect(GDP.models.DataSetModel.prototype.isInFilter.calls.length).toBe(6);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[3].args[0].algorithms).toEqual(['ALG1', 'ALG2', 'ALG3']);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[4].args[0].algorithms).toEqual(['ALG1', 'ALG2', 'ALG3']);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[5].args[0].algorithms).toEqual(['ALG1', 'ALG2', 'ALG3']);

			testView.filterByAlgorithm({target : {checked : false, value : 'TYPE1'}});
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls.length).toBe(9);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[6].args[0].algorithms).toEqual(['ALG3']);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[7].args[0].algorithms).toEqual(['ALG3']);
			expect(GDP.models.DataSetModel.prototype.isInFilter.calls[8].args[0].algorithms).toEqual(['ALG3']);
		});

	});

});<|endoftext|>


<commit_before>var types = require("../lib/HAP-NodeJS/accessories/types.js");
var httpSync = require('http-sync');

function Spark(log, config) {
  this.log = log;
  this.name = config["name"];
  this.token = config["access_token"];
  this.device = config["device_id"];
  this.hue = 0;
  this.saturation = 100;
  this.brightness = 100;
  this.speed = 170;
  this.animation = 0;
  this.animations = readAnimations(this);
}

function setColor(that, r, g, b) {
  var result = callFunction(that, 'setColor', r+","+g+","+b);
  console.log("Settings color "+r+","+g+","+b);
  console.log(result);
}

function animate(that, animation, brightness, speed) {
  var result = callFunction(that, 'animate', animation+","+brightness+","+speed);
  console.log(result);
}

function readAnimations(that) {
  return readVariable(that, 'animations').split(",");
}

function readVariable(that, variable) {
  var token = that.token;
  var device = that.device;
  var request = httpSync.request({
    method: 'GET',
    headers: {"Authorization": "Bearer "+token},
    body: '',

    protocol: 'https',
    host: 'api.spark.io',
    port: 443,
    path: '/v1/devices/'+device+'/'+variable
  });
  var response = request.end();
  var body = JSON.parse(response.body.toString());
  return body.result;
}

function callFunction(that, func, value) {
  var token = that.token;
  var device = that.device;
  var request = httpSync.request({
    method: 'POST',
    headers: {"Authorization": "Bearer "+token},
    body: value,

    protocol: 'https',
    host: 'api.spark.io',
    port: 443,
    path: '/v1/devices/'+device+'/'+func
  });
  var response = request.end();
  var body = JSON.parse(response.body.toString());
  return body;
}

function HSVtoRGB(h, s, v) {
    var r, g, b, i, f, p, q, t;
    if (h && s === undefined && v === undefined) {
        s = h.s, v = h.v, h = h.h;
    }
    i = Math.floor(h * 6);
    f = h * 6 - i;
    p = v * (1 - s);
    q = v * (1 - f * s);
    t = v * (1 - (1 - f) * s);
    switch (i % 6) {
        case 0: r = v, g = t, b = p; break;
        case 1: r = q, g = v, b = p; break;
        case 2: r = p, g = v, b = t; break;
        case 3: r = p, g = q, b = v; break;
        case 4: r = t, g = p, b = v; break;
        case 5: r = v, g = p, b = q; break;
    }
    return {
        r: Math.floor(r * 255),
        g: Math.floor(g * 255),
        b: Math.floor(b * 255)
    };
}

Spark.prototype = {

  setPowerState: function(powerOn) {

    var binaryState = powerOn ? "0,255,0" : "0,0,0";
    var that = this;

    this.log("Setting power state of " + this.name + " to " + powerOn);

    if (powerOn) {
      this.animation = 1;
      this.brightness = 100;
      this.speed = 200;
      animate(that, this.animation, 255, 200);
    } else {
      setColor(that, 0, 0, 0);
    }
  },

  setHueValue: function(value) {
    var that = this;

    this.log("Setting hue value to " + value);
    this.hue = value;

    rgb = HSVtoRGB(this.hue / 360, this.saturation / 100, this.brightness / 100);
    setColor(that, rgb.r, rgb.g, rgb.b);
  },

  setSaturationValue: function(value) {
    var that = this;

    this.log("Setting saturation value to " + value);
    this.saturation = value;

    rgb = HSVtoRGB(this.hue / 360, this.saturation / 100, this.brightness / 100);
    setColor(that, rgb.r, rgb.g, rgb.b);
  },

  setBrightnessLevel: function(value) {
    var that = this;

    this.log("Setting brightness level to " + value);
    this.brightness = value;

    rgb = HSVtoRGB(this.hue / 360, this.saturation / 100, this.brightness / 100);
    setColor(that, rgb.r, rgb.g, rgb.b);
  },

  setAnimation: function(value) {
    var that = this;

    this.log("Setting animation to " + value);
    this.animation = value;

    animate(that, this.animation, this.brightness, this.speed);
  },

  setSpeed: function(value) {
    var that = this;

    this.log("Setting speed to " + value);
    this.speed = value;

    animate(that, this.animation, this.brightness, this.speed);
  },

  getServices: function() {
    var that = this;
    return [{
      sType: types.ACCESSORY_INFORMATION_STYPE,
      characteristics: [{
        cType: types.NAME_CTYPE,
        onUpdate: null,
        perms: ["pr"],
        format: "string",
        initialValue: this.name,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Name of the accessory",
        designedMaxLength: 255
      },{
        cType: types.MANUFACTURER_CTYPE,
        onUpdate: null,
        perms: ["pr"],
        format: "string",
        initialValue: "X10",
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Manufacturer",
        designedMaxLength: 255
      },{
        cType: types.MODEL_CTYPE,
        onUpdate: null,
        perms: ["pr"],
        format: "string",
        initialValue: "Rev-1",
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Model",
        designedMaxLength: 255
      },{
        cType: types.SERIAL_NUMBER_CTYPE,
        onUpdate: null,
        perms: ["pr"],
        format: "string",
        initialValue: "A1S2NASF88EW",
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "SN",
        designedMaxLength: 255
      },{
        cType: types.IDENTIFY_CTYPE,
        onUpdate: null,
        perms: ["pw"],
        format: "bool",
        initialValue: false,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Identify Accessory",
        designedMaxLength: 1
      }]
    },{
      sType: types.LIGHTBULB_STYPE,
      characteristics: [{
        cType: types.NAME_CTYPE,
        onUpdate: null,
        perms: ["pr"],
        format: "string",
        initialValue: this.name,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Name of service",
        designedMaxLength: 255
      },{
        cType: types.POWER_STATE_CTYPE,
        onUpdate: function(value) { that.setPowerState(value); },
        perms: ["pw","pr","ev"],
        format: "bool",
        initialValue: false,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Change the power state of a Variable",
        designedMaxLength: 1
      },{
        cType: types.BRIGHTNESS_CTYPE,
        onUpdate: function(value) { that.setBrightnessLevel(value); },
        perms: ["pw","pr","ev"],
        format: "int",
        initialValue: 100,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Adjust Brightness of Light",
        designedMinValue: 0,
        designedMaxValue: 100,
        designedMinStep: 1,
        unit: "%"
      },{
        cType: types.HUE_CTYPE,
        onUpdate: function(value) { that.setHueValue(value); },
        perms: ["pw","pr","ev"],
        format: "int",
        initialValue: 0,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Adjust Hue of Light",
        designedMinValue: 0,
        designedMaxValue: 360,
        designedMinStep: 1,
        unit: "arcdegrees"
      },{
        cType: types.SATURATION_CTYPE,
        onUpdate: function(value) { that.setSaturationValue(value); },
        perms: ["pw","pr","ev"],
        format: "int",
        initialValue: 100,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Adjust Saturation of Light",
        designedMinValue: 0,
        designedMaxValue: 100,
        designedMinStep: 1,
        unit: "%"
      },{
        cType: "0000000A-0000-1000-8000-0026BB765291",
        onUpdate: function(value) { that.setAnimation(value); },
        perms: ["pw","pr","ev"],
        format: "int",
        initialValue: 0,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Set animation of Light",
        designedMinValue: 0,
        designedMaxValue: this.animations.length,
        designedMinStep: 1
      },{
        cType: "0000000B-0000-1000-8000-0026BB765291",
        onUpdate: function(value) { that.setSpeed(value); },
        perms: ["pw","pr","ev"],
        format: "int",
        initialValue: 170,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Set animation speed of Light",
        designedMinValue: 1,
        designedMaxValue: 200,
        designedMinStep: 1
      }]
    }];
  }
};

module.exports.accessory = Spark;
<commit_msg>fix typo<commit_after>var types = require("../lib/HAP-NodeJS/accessories/types.js");
var httpSync = require('http-sync');

function Spark(log, config) {
  this.log = log;
  this.name = config["name"];
  this.token = config["access_token"];
  this.device = config["device_id"];
  this.hue = 0;
  this.saturation = 100;
  this.brightness = 100;
  this.speed = 170;
  this.animation = 0;
  this.animations = readAnimations(this);
}

function setColor(that, r, g, b) {
  var result = callFunction(that, 'setColor', r+","+g+","+b);
  console.log("Setting color "+r+","+g+","+b);
  console.log(result);
}

function animate(that, animation, brightness, speed) {
  var result = callFunction(that, 'animate', animation+","+brightness+","+speed);
  console.log(result);
}

function readAnimations(that) {
  return readVariable(that, 'animations').split(",");
}

function readVariable(that, variable) {
  var token = that.token;
  var device = that.device;
  var request = httpSync.request({
    method: 'GET',
    headers: {"Authorization": "Bearer "+token},
    body: '',

    protocol: 'https',
    host: 'api.spark.io',
    port: 443,
    path: '/v1/devices/'+device+'/'+variable
  });
  var response = request.end();
  var body = JSON.parse(response.body.toString());
  return body.result;
}

function callFunction(that, func, value) {
  var token = that.token;
  var device = that.device;
  var request = httpSync.request({
    method: 'POST',
    headers: {"Authorization": "Bearer "+token},
    body: value,

    protocol: 'https',
    host: 'api.spark.io',
    port: 443,
    path: '/v1/devices/'+device+'/'+func
  });
  var response = request.end();
  var body = JSON.parse(response.body.toString());
  return body;
}

function HSVtoRGB(h, s, v) {
    var r, g, b, i, f, p, q, t;
    if (h && s === undefined && v === undefined) {
        s = h.s, v = h.v, h = h.h;
    }
    i = Math.floor(h * 6);
    f = h * 6 - i;
    p = v * (1 - s);
    q = v * (1 - f * s);
    t = v * (1 - (1 - f) * s);
    switch (i % 6) {
        case 0: r = v, g = t, b = p; break;
        case 1: r = q, g = v, b = p; break;
        case 2: r = p, g = v, b = t; break;
        case 3: r = p, g = q, b = v; break;
        case 4: r = t, g = p, b = v; break;
        case 5: r = v, g = p, b = q; break;
    }
    return {
        r: Math.floor(r * 255),
        g: Math.floor(g * 255),
        b: Math.floor(b * 255)
    };
}

Spark.prototype = {

  setPowerState: function(powerOn) {

    var binaryState = powerOn ? "0,255,0" : "0,0,0";
    var that = this;

    this.log("Setting power state of " + this.name + " to " + powerOn);

    if (powerOn) {
      this.animation = 1;
      this.brightness = 100;
      this.speed = 200;
      animate(that, this.animation, 255, 200);
    } else {
      setColor(that, 0, 0, 0);
    }
  },

  setHueValue: function(value) {
    var that = this;

    this.log("Setting hue value to " + value);
    this.hue = value;

    rgb = HSVtoRGB(this.hue / 360, this.saturation / 100, this.brightness / 100);
    setColor(that, rgb.r, rgb.g, rgb.b);
  },

  setSaturationValue: function(value) {
    var that = this;

    this.log("Setting saturation value to " + value);
    this.saturation = value;

    rgb = HSVtoRGB(this.hue / 360, this.saturation / 100, this.brightness / 100);
    setColor(that, rgb.r, rgb.g, rgb.b);
  },

  setBrightnessLevel: function(value) {
    var that = this;

    this.log("Setting brightness level to " + value);
    this.brightness = value;

    rgb = HSVtoRGB(this.hue / 360, this.saturation / 100, this.brightness / 100);
    setColor(that, rgb.r, rgb.g, rgb.b);
  },

  setAnimation: function(value) {
    var that = this;

    this.log("Setting animation to " + value);
    this.animation = value;

    animate(that, this.animation, this.brightness, this.speed);
  },

  setSpeed: function(value) {
    var that = this;

    this.log("Setting speed to " + value);
    this.speed = value;

    animate(that, this.animation, this.brightness, this.speed);
  },

  getServices: function() {
    var that = this;
    return [{
      sType: types.ACCESSORY_INFORMATION_STYPE,
      characteristics: [{
        cType: types.NAME_CTYPE,
        onUpdate: null,
        perms: ["pr"],
        format: "string",
        initialValue: this.name,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Name of the accessory",
        designedMaxLength: 255
      },{
        cType: types.MANUFACTURER_CTYPE,
        onUpdate: null,
        perms: ["pr"],
        format: "string",
        initialValue: "X10",
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Manufacturer",
        designedMaxLength: 255
      },{
        cType: types.MODEL_CTYPE,
        onUpdate: null,
        perms: ["pr"],
        format: "string",
        initialValue: "Rev-1",
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Model",
        designedMaxLength: 255
      },{
        cType: types.SERIAL_NUMBER_CTYPE,
        onUpdate: null,
        perms: ["pr"],
        format: "string",
        initialValue: "A1S2NASF88EW",
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "SN",
        designedMaxLength: 255
      },{
        cType: types.IDENTIFY_CTYPE,
        onUpdate: null,
        perms: ["pw"],
        format: "bool",
        initialValue: false,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Identify Accessory",
        designedMaxLength: 1
      }]
    },{
      sType: types.LIGHTBULB_STYPE,
      characteristics: [{
        cType: types.NAME_CTYPE,
        onUpdate: null,
        perms: ["pr"],
        format: "string",
        initialValue: this.name,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Name of service",
        designedMaxLength: 255
      },{
        cType: types.POWER_STATE_CTYPE,
        onUpdate: function(value) { that.setPowerState(value); },
        perms: ["pw","pr","ev"],
        format: "bool",
        initialValue: false,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Change the power state of a Variable",
        designedMaxLength: 1
      },{
        cType: types.BRIGHTNESS_CTYPE,
        onUpdate: function(value) { that.setBrightnessLevel(value); },
        perms: ["pw","pr","ev"],
        format: "int",
        initialValue: 100,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Adjust Brightness of Light",
        designedMinValue: 0,
        designedMaxValue: 100,
        designedMinStep: 1,
        unit: "%"
      },{
        cType: types.HUE_CTYPE,
        onUpdate: function(value) { that.setHueValue(value); },
        perms: ["pw","pr","ev"],
        format: "int",
        initialValue: 0,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Adjust Hue of Light",
        designedMinValue: 0,
        designedMaxValue: 360,
        designedMinStep: 1,
        unit: "arcdegrees"
      },{
        cType: types.SATURATION_CTYPE,
        onUpdate: function(value) { that.setSaturationValue(value); },
        perms: ["pw","pr","ev"],
        format: "int",
        initialValue: 100,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Adjust Saturation of Light",
        designedMinValue: 0,
        designedMaxValue: 100,
        designedMinStep: 1,
        unit: "%"
      },{
        cType: "0000000A-0000-1000-8000-0026BB765291",
        onUpdate: function(value) { that.setAnimation(value); },
        perms: ["pw","pr","ev"],
        format: "int",
        initialValue: 0,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Set animation of Light",
        designedMinValue: 0,
        designedMaxValue: this.animations.length,
        designedMinStep: 1
      },{
        cType: "0000000B-0000-1000-8000-0026BB765291",
        onUpdate: function(value) { that.setSpeed(value); },
        perms: ["pw","pr","ev"],
        format: "int",
        initialValue: 170,
        supportEvents: false,
        supportBonjour: false,
        manfDescription: "Set animation speed of Light",
        designedMinValue: 1,
        designedMaxValue: 200,
        designedMinStep: 1
      }]
    }];
  }
};

module.exports.accessory = Spark;
<|endoftext|>


<commit_before>'use strict';

var baseUrl = 'http://127.0.0.1:8000/';

/**
 * @ngdoc overview
 * @name flyguyApp
 * @description
 * # flyguyApp
 *
 * Config module of the application.
 */
angular.module('flyguyApp')
    .constant('config', {
        baseUrl: baseUrl
    });

angular.module('flyguyApp').config(function(RestangularProvider, config) {
        RestangularProvider.setBaseUrl(config.baseUrl + 'api');
        RestangularProvider.setRequestSuffix('/');
        RestangularProvider.addResponseInterceptor(function(data, operation) {
            if (operation === 'getList') {
                data = data.results;
            }
            return data;
        });
    });
<commit_msg>Changed api endpoint to appyharry<commit_after>'use strict';

var baseUrl = 'http://flyguy-service.appyharry.com/';

/**
 * @ngdoc overview
 * @name flyguyApp
 * @description
 * # flyguyApp
 *
 * Config module of the application.
 */
angular.module('flyguyApp')
    .constant('config', {
        baseUrl: baseUrl
    });

angular.module('flyguyApp').config(function(RestangularProvider, config) {
        RestangularProvider.setBaseUrl(config.baseUrl + 'api');
        RestangularProvider.setRequestSuffix('/');
        RestangularProvider.addResponseInterceptor(function(data, operation) {
            if (operation === 'getList') {
                data = data.results;
            }
            return data;
        });
    });
<|endoftext|>


<commit_before>let currentBrowser;

module.exports = {
  tags: ['component', 'blockquote', 'web component'],
  'Bolt Blockquote': function(browser) {
    const { testingUrl } = browser.globals;
    console.log(`global browser url: ${testingUrl}`);
    currentBrowser = '--' + browser.currentEnv || 'chrome';
    let testName = 'bolt-blockquote';

    browser
      .url(
        `${testingUrl}/pattern-lab/patterns/02-components-blockquote-10-blockquote-alignItems-variation/02-components-blockquote-10-blockquote-alignItems-variation.html`,
      )
      .waitForElementVisible('bolt-blockquote', 1000)
      .assert.elementPresent('img[slot="logo"]')
      .execute(
        function(data) {
          return document.querySelector('bolt-blockquote cite[slot="author-name"]').textContent;
        },
        [],
        function(result) {
          browser.assert.ok(
            result.value === 'Michelangelo di Lodovico Buonarroti Simoni',
            `verified that <bolt-blockquote> rendered author text.`,
          );
        },
      )
      .saveScreenshot(
        `screenshots/bolt-blockquote/${testName}--${currentBrowser}.png`,
      )
      .end();
  },
}
<commit_msg>chore: add missing semicolon<commit_after>let currentBrowser;

module.exports = {
  tags: ['component', 'blockquote', 'web component'],
  'Bolt Blockquote': function(browser) {
    const { testingUrl } = browser.globals;
    console.log(`global browser url: ${testingUrl}`);
    currentBrowser = '--' + browser.currentEnv || 'chrome';
    let testName = 'bolt-blockquote';

    browser
      .url(
        `${testingUrl}/pattern-lab/patterns/02-components-blockquote-10-blockquote-alignItems-variation/02-components-blockquote-10-blockquote-alignItems-variation.html`,
      )
      .waitForElementVisible('bolt-blockquote', 1000)
      .assert.elementPresent('img[slot="logo"]')
      .execute(
        function(data) {
          return document.querySelector('bolt-blockquote cite[slot="author-name"]').textContent;
        },
        [],
        function(result) {
          browser.assert.ok(
            result.value === 'Michelangelo di Lodovico Buonarroti Simoni',
            `verified that <bolt-blockquote> rendered author text.`,
          );
        },
      )
      .saveScreenshot(
        `screenshots/bolt-blockquote/${testName}--${currentBrowser}.png`,
      )
      .end();
  },
};
<|endoftext|>


<commit_before>'use strict';

/* Services */

angular.module('app.directives', [])

  .directive('hexus', function ($timeout, usStatesHex) {
    return {
      restrict: 'A',
    // , templateUrl: 'partials/navbar.html'
      scope: {
          data: '=',
          statuses: '='
      },
      link: function($scope, el, attrs) {

        el.html('
Loading...
');

        $scope.$watch('statuses', function () {
          if ($scope.statuses !== undefined){
            $timeout(function () {
              el.html('');

              var states = usStatesHex.data;

              // Setup: dimensions
              var margin = {top: 10, right: 10, bottom: 10, left: 10};
              var width = el[0].offsetWidth - margin.left - margin.right;
              var height = el[0].offsetHeight - margin.top - margin.bottom;

              // Setup: scales
              var size = d3.scale.linear()
                  .range([0, height]);

              // Setup: SVG container
              var svg = d3.select(el[0]).append("svg")
                .attr("width", width + margin.left + margin.right)
                .attr("height", height + margin.top + margin.bottom)
              .append("g")
                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

              // Binding: scales
              size.domain(d3.extent(
                states.map(function(d) { return d.yExtent[0]; })
                .concat(states.map(function(d) { return d.yExtent[1]; }))
              ));

              var lineFunction = d3.svg.line()
                .x(function(d) { return size(d[0]); })
                .y(function(d) { return size(d[1]); })
                .interpolate('linear');

              svg.selectAll('.hex')
                .data(states)
              .enter().append('path')
                .attr('d', function(d){return lineFunction(d.hex); })
                .attr('stroke', 'white')
                .attr('stroke-width', 1)
                .attr('fill', function (d) {

                  if ($scope.statuses[d.abbr]) {
                    if ($scope.statuses[d.abbr].loading) {
                      return '#EEEEEE'
                    } else if ($scope.statuses[d.abbr].available) {
                      return 'steelblue'
                    } else {
                      return '#CCCCCC'
                    }
                  } else {
                    return '#EEEEEE'
                  }
                })

              svg.selectAll('.hextext')
                .data(states)
              .enter().append('text')
                .text(function (d) { return d.abbr })
                .attr('x', function(d){ return size(d.x) })
                .attr('y', function(d){ return size(d.y) })
                .attr('font-family', 'sans-serif')
                .attr('font-size', '14px')
                .attr('fill', 'white')
                .attr('text-anchor', 'middle')
                .attr('alignment-baseline', 'middle')

            }, 0, false);
          }
        }, true);
      }
    }
  })
<commit_msg>center hex us map<commit_after>'use strict';

/* Services */

angular.module('app.directives', [])

  .directive('hexus', function ($timeout, usStatesHex) {
    return {
      restrict: 'A',
    // , templateUrl: 'partials/navbar.html'
      scope: {
          data: '=',
          statuses: '='
      },
      link: function($scope, el, attrs) {

        el.html('
Loading...
');

        $scope.$watch('statuses', function () {
          if ($scope.statuses !== undefined){
            $timeout(function () {
              el.html('');

              var states = usStatesHex.data;

              // Setup: dimensions
              var margin = {top: 24, right: 0, bottom: 24, left: 0};
              var width = el[0].offsetWidth - margin.left - margin.right;
              var height = el[0].offsetHeight - margin.top - margin.bottom;

              // Setup: scales
              var size = d3.scale.linear()
                  .range([0, height]);

              // Setup: SVG container
              var svg = d3.select(el[0]).append("svg")
                .attr("width", width + margin.left + margin.right)
                .attr("height", height + margin.top + margin.bottom)
              .append("g")
                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

              // Binding: scales
              size.domain(d3.extent(
                states.map(function(d) { return d.yExtent[0]; })
                .concat(states.map(function(d) { return d.yExtent[1]; }))
              ));

              var xExtent = d3.extent(
                states.map(function(d) { return d.xExtent[0]; })
                .concat(states.map(function(d) { return d.xExtent[1]; }))
              )
              var xOffset = -size(xExtent[0]) + (width / 2 - ( size(xExtent[1]) - size(xExtent[0]) ) / 2 )

              var lineFunction = d3.svg.line()
                .x(function(d) { return xOffset + size(d[0]); })
                .y(function(d) { return size(d[1]); })
                .interpolate('linear');

              svg.selectAll('.hex')
                .data(states)
              .enter().append('path')
                .attr('d', function(d){return lineFunction(d.hex); })
                .attr('stroke', 'white')
                .attr('stroke-width', 1)
                .attr('fill', function (d) {

                  if ($scope.statuses[d.abbr]) {
                    if ($scope.statuses[d.abbr].loading) {
                      return '#EEEEEE'
                    } else if ($scope.statuses[d.abbr].available) {
                      return 'steelblue'
                    } else {
                      return '#CCCCCC'
                    }
                  } else {
                    return '#EEEEEE'
                  }
                })

              svg.selectAll('.hextext')
                .data(states)
              .enter().append('text')
                .text(function (d) { return d.abbr })
                .attr('x', function(d){ return xOffset + size(d.x) })
                .attr('y', function(d){ return size(d.y) })
                .attr('font-family', 'sans-serif')
                .attr('font-size', '14px')
                .attr('fill', 'white')
                .attr('text-anchor', 'middle')
                .attr('alignment-baseline', 'middle')

            }, 0, false);
          }
        }, true);
      }
    }
  })
<|endoftext|>


<commit_before>var env, User, Contact, Email, Phone, Message, Post, Comment;
var get = Ember.get, set = Ember.set;

var attr = DS.attr, hasMany = DS.hasMany, belongsTo = DS.belongsTo;

function stringify(string) {
  return function() { return string; };
}

module("integration/relationships/has_many - Has-Many Relationships", {
  setup: function() {
    User = DS.Model.extend({
      name: attr('string'),
      messages: hasMany('message', { polymorphic: true }),
      contacts: hasMany()
    });

    Contact = DS.Model.extend({
      user: belongsTo('user')
    });

    Email = Contact.extend({
      email: attr('string')
    });

    Phone = Contact.extend({
      number: attr('string')
    });

    Message = DS.Model.extend({
      user: belongsTo('user'),
      created_at: attr('date')
    });
    Message.toString = stringify('Message');

    Post = Message.extend({
      title: attr('string'),
      comments: hasMany('comment')
    });
    Post.toString = stringify('Post');

    Comment = Message.extend({
      body: DS.attr('string'),
      message: DS.belongsTo('post', { polymorphic: true })
    });
    Comment.toString = stringify('Comment');

    env = setupStore({
      user: User,
      contact: Contact,
      email: Email,
      phone: Phone,
      post: Post,
      comment: Comment,
      message: Message
    });
  },

  teardown: function() {
    env.container.destroy();
  }
});

test("When a hasMany relationship is accessed, the adapter's findMany method should not be called if all the records in the relationship are already loaded", function() {
  expect(0);

  env.adapter.findMany = function() {
    ok(false, "The adapter's find method should not be called");
  };

  env.store.push('post', { id: 1, comments: [ 1 ] });
  env.store.push('comment', { id: 1 });

  env.store.find('post', 1).then(async(function(post) {
    post.get('comments');
  }));
});

// This tests the case where a serializer materializes a has-many
// relationship as a reference that it can fetch lazily. The most
// common use case of this is to provide a URL to a collection that
// is loaded later.
test("A serializer can materialize a hasMany as an opaque token that can be lazily fetched via the adapter's findHasMany hook", function() {
  Post.reopen({
    comments: DS.hasMany('comment', { async: true })
  });

  // When the store asks the adapter for the record with ID 1,
  // provide some fake data.
  env.adapter.find = function(store, type, id) {
    equal(type, Post, "find type was Post");
    equal(id, "1", "find id was 1");

    return Ember.RSVP.resolve({ id: 1, links: { comments: "/posts/1/comments" } });
  };

  env.adapter.findMany = function() {
    throw new Error("Adapter's findMany should not be called");
  };

  env.adapter.findHasMany = function(store, record, link, relationship) {
    equal(relationship.type, Comment, "findHasMany relationship type was Comment");
    equal(relationship.key, 'comments', "findHasMany relationship key was comments");
    equal(link, "/posts/1/comments", "findHasMany link was /posts/1/comments");

    return Ember.RSVP.resolve([
      { id: 1, body: "First" },
      { id: 2, body: "Second" }
    ]);
  };

  env.store.find('post', 1).then(async(function(post) {
    return post.get('comments');
  })).then(async(function(comments) {
    equal(comments.get('isLoaded'), true, "comments are loaded");
    equal(comments.get('length'), 2, "comments have 2 length");
  }));
});

test("An updated `links` value should invalidate a relationship cache", function() {
  Post.reopen({
    comments: DS.hasMany('comment', { async: true })
  });

  env.adapter.createRecord = function(store, type, record) {
    var data = record.serialize();
    return Ember.RSVP.resolve({ id: 1, links: { comments: "/posts/1/comments" } });
  };

  env.adapter.findHasMany = function(store, record, link, relationship) {
    equal(relationship.type, Comment, "findHasMany relationship type was Comment");
    equal(relationship.key, 'comments', "findHasMany relationship key was comments");
    equal(link, "/posts/1/comments", "findHasMany link was /posts/1/comments");

    return Ember.RSVP.resolve([
      { id: 1, body: "First" },
      { id: 2, body: "Second" }
    ]);
  };

  env.store.createRecord('post', {}).save().then(async(function(post) {
    return post.get('comments');
  })).then(async(function(comments) {
    equal(comments.get('isLoaded'), true, "comments are loaded");
    equal(comments.get('length'), 2, "comments have 2 length");
  }));
});

test("When a polymorphic hasMany relationship is accessed, the adapter's findMany method should not be called if all the records in the relationship are already loaded", function() {
  expect(1);

  env.adapter.findMany = function() {
    ok(false, "The adapter's find method should not be called");
  };

  env.store.push('user', { id: 1, messages: [ {id: 1, type: 'post'}, {id: 3, type: 'comment'} ] });
  env.store.push('post', { id: 1 });
  env.store.push('comment', { id: 3 });

  env.store.find('user', 1).then(async(function(user) {
    var messages = user.get('messages');
    equal(messages.get('length'), 2, "The messages are correctly loaded");
  }));
});

test("When a polymorphic hasMany relationship is accessed, the store can call multiple adapters' findMany method if the records are not loaded", function() {
  User.reopen({
    messages: hasMany('message', { polymorphic: true, async: true })
  });

  env.adapter.findMany = function(store, type) {
    if (type === Post) {
      return Ember.RSVP.resolve([{ id: 1 }]);
    } else if (type === Comment) {
      return Ember.RSVP.resolve([{ id: 3 }]);
    }
  };

  env.store.push('user', { id: 1, messages: [ {id: 1, type: 'post'}, {id: 3, type: 'comment'} ] });

  env.store.find('user', 1).then(async(function(user) {
    return user.get('messages');
  })).then(async(function(messages) {
    equal(messages.get('length'), 2, "The messages are correctly loaded");
  }));
});

test("Type can be inferred from the key of a hasMany relationship", function() {
  expect(1);
  env.store.push('user', { id: 1, contacts: [ 1 ] });
  env.store.push('contact', { id: 1 });
  env.store.find('user', 1).then(async(function(user) {
    return user.get('contacts');
  })).then(async(function(contacts) {
    equal(contacts.get('length'), 1, "The contacts relationship is correctly set up");
  }));
});

test("Type can be inferred from the key of an async hasMany relationship", function() {
  User.reopen({
    contacts: DS.hasMany({ async: true })
  });

  expect(1);
  env.store.push('user', { id: 1, contacts: [ 1 ] });
  env.store.push('contact', { id: 1 });
  env.store.find('user', 1).then(async(function(user) {
    return user.get('contacts');
  })).then(async(function(contacts) {
    equal(contacts.get('length'), 1, "The contacts relationship is correctly set up");
  }));
});

test("Polymorphic relationships work with a hasMany whose type is inferred", function() {
  User.reopen({
    contacts: DS.hasMany({ polymorphic: true })
  });

  expect(1);
  env.store.push('user', { id: 1, contacts: [ { id: 1, type: 'email' }, { id: 2, type: 'phone' } ] });
  env.store.push('email', { id: 1 });
  env.store.push('phone', { id: 2 });
  env.store.find('user', 1).then(async(function(user) {
    return user.get('contacts');
  })).then(async(function(contacts) {
    equal(contacts.get('length'), 2, "The contacts relationship is correctly set up");
  }));
});

test("A record can't be created from a polymorphic hasMany relationship", function() {
  env.store.push('user', { id: 1, messages: [] });

  env.store.find('user', 1).then(async(function(user) {
    return user.get('messages');
  })).then(async(function(messages) {
    expectAssertion(function() {
      messages.createRecord();
    }, /You cannot add 'message' records to this polymorphic relationship/);
  }));
});

test("Only records of the same type can be added to a monomorphic hasMany relationship", function() {
  expect(1);
  env.store.push('post', { id: 1, comments: [] });
  env.store.push('post', { id: 2 });

  Ember.RSVP.all([ env.store.find('post', 1), env.store.find('post', 2) ]).then(async(function(records) {
    expectAssertion(function() {
      records[0].get('comments').pushObject(records[1]);
    }, /You cannot add 'post' records to this relationship/);
  }));

});

test("Only records of the same base type can be added to a polymorphic hasMany relationship", function() {
  expect(2);
  env.store.push('user', { id: 1, messages: [] });
  env.store.push('user', { id: 2, messages: [] });
  env.store.push('post', { id: 1, comments: [] });
  env.store.push('comment', { id: 3 });

  var asyncRecords = Ember.RSVP.hash({
    user: env.store.find('user', 1),
    anotherUser: env.store.find('user', 2),
    post: env.store.find('post', 1),
    comment: env.store.find('comment', 3)
  });

  asyncRecords.then(async(function(records) {
    records.messages = records.user.get('messages');
    return Ember.RSVP.hash(records);
  })).then(async(function(records) {
    records.messages.pushObject(records.post);
    records.messages.pushObject(records.comment);
    equal(records.messages.get('length'), 2, "The messages are correctly added");

    expectAssertion(function() {
      records.messages.pushObject(records.anotherUser);
    }, /You cannot add 'user' records to this relationship/);
  }));
});

test("A record can be removed from a polymorphic association", function() {
  expect(3);

  env.store.push('user', { id: 1 , messages: [{id: 3, type: 'comment'}]});
  env.store.push('comment', { id: 3 });

  var asyncRecords = Ember.RSVP.hash({
    user: env.store.find('user', 1),
    comment: env.store.find('comment', 3)
  });

  asyncRecords.then(async(function(records) {
    records.messages = records.user.get('messages');
    return Ember.RSVP.hash(records);
  })).then(async(function(records) {
    equal(records.messages.get('length'), 1, "The user has 1 message");

    var removedObject = records.messages.popObject();

    equal(removedObject, records.comment, "The message is correctly removed");
    equal(records.messages.get('length'), 0, "The user does not have any messages");
  }));
});

test("When a record is created on the client, its hasMany arrays should be in a loaded state", function() {
  expect(3);

  var post;

  Ember.run(function() {
    post = env.store.createRecord('post');
  });

  ok(get(post, 'isLoaded'), "The post should have isLoaded flag");

  var comments = get(post, 'comments');

  equal(get(comments, 'length'), 0, "The comments should be an empty array");

  ok(get(comments, 'isLoaded'), "The comments should have isLoaded flag");

});

test("When a record is created on the client, its async hasMany arrays should be in a loaded state", function() {
  expect(4);

  Post.reopen({
    comments: DS.hasMany('comment', { async: true })
  });

  var post = Ember.run(function() {
    return env.store.createRecord('post');
  });

  ok(get(post, 'isLoaded'), "The post should have isLoaded flag");

  get(post, 'comments').then(function(comments) {
    ok(true, "Comments array successfully resolves");
    equal(get(comments, 'length'), 0, "The comments should be an empty array");
    ok(get(comments, 'isLoaded'), "The comments should have isLoaded flag");
  });

});

test("a records SYNC HM relationship property is readOnly", function(){
  expect(1);
  var post = Ember.run(function() {
    return env.store.createRecord('post');
  });

  raises(function(){
    post.set('comments');
  }, 'Cannot Set: comments on: ' + Ember.inspect(post));
});

test("a records ASYNC HM relationship property is readOnly", function(){
  expect(1);
  Post.reopen({
    comments: DS.hasMany('comment', { async: true })
  });

  var post = Ember.run(function() {
    return env.store.createRecord('post');
  });

  raises(function(){
    post.set('comments');
  }, 'Cannot Set: comments on: ' + Ember.inspect(post));
});
<commit_msg>Add failing test for hasMany relationships<commit_after>var env, User, Contact, Email, Phone, Message, Post, Comment;
var get = Ember.get, set = Ember.set;

var attr = DS.attr, hasMany = DS.hasMany, belongsTo = DS.belongsTo;

function stringify(string) {
  return function() { return string; };
}

module("integration/relationships/has_many - Has-Many Relationships", {
  setup: function() {
    User = DS.Model.extend({
      name: attr('string'),
      messages: hasMany('message', { polymorphic: true }),
      contacts: hasMany()
    });

    Contact = DS.Model.extend({
      user: belongsTo('user')
    });

    Email = Contact.extend({
      email: attr('string')
    });

    Phone = Contact.extend({
      number: attr('string')
    });

    Message = DS.Model.extend({
      user: belongsTo('user'),
      created_at: attr('date')
    });
    Message.toString = stringify('Message');

    Post = Message.extend({
      title: attr('string'),
      comments: hasMany('comment')
    });
    Post.toString = stringify('Post');

    Comment = Message.extend({
      body: DS.attr('string'),
      message: DS.belongsTo('post', { polymorphic: true })
    });
    Comment.toString = stringify('Comment');

    env = setupStore({
      user: User,
      contact: Contact,
      email: Email,
      phone: Phone,
      post: Post,
      comment: Comment,
      message: Message
    });
  },

  teardown: function() {
    env.container.destroy();
  }
});

test("When a hasMany relationship is accessed, the adapter's findMany method should not be called if all the records in the relationship are already loaded", function() {
  expect(0);

  env.adapter.findMany = function() {
    ok(false, "The adapter's find method should not be called");
  };

  env.store.push('post', { id: 1, comments: [ 1 ] });
  env.store.push('comment', { id: 1 });

  env.store.find('post', 1).then(async(function(post) {
    post.get('comments');
  }));
});

// This tests the case where a serializer materializes a has-many
// relationship as a reference that it can fetch lazily. The most
// common use case of this is to provide a URL to a collection that
// is loaded later.
test("A serializer can materialize a hasMany as an opaque token that can be lazily fetched via the adapter's findHasMany hook", function() {
  Post.reopen({
    comments: DS.hasMany('comment', { async: true })
  });

  // When the store asks the adapter for the record with ID 1,
  // provide some fake data.
  env.adapter.find = function(store, type, id) {
    equal(type, Post, "find type was Post");
    equal(id, "1", "find id was 1");

    return Ember.RSVP.resolve({ id: 1, links: { comments: "/posts/1/comments" } });
  };

  env.adapter.findMany = function() {
    throw new Error("Adapter's findMany should not be called");
  };

  env.adapter.findHasMany = function(store, record, link, relationship) {
    equal(relationship.type, Comment, "findHasMany relationship type was Comment");
    equal(relationship.key, 'comments', "findHasMany relationship key was comments");
    equal(link, "/posts/1/comments", "findHasMany link was /posts/1/comments");

    return Ember.RSVP.resolve([
      { id: 1, body: "First" },
      { id: 2, body: "Second" }
    ]);
  };

  env.store.find('post', 1).then(async(function(post) {
    return post.get('comments');
  })).then(async(function(comments) {
    equal(comments.get('isLoaded'), true, "comments are loaded");
    equal(comments.get('length'), 2, "comments have 2 length");
  }));
});

test("An updated `links` value should invalidate a relationship cache", function() {
  Post.reopen({
    comments: DS.hasMany('comment', { async: true })
  });

  env.adapter.createRecord = function(store, type, record) {
    var data = record.serialize();
    return Ember.RSVP.resolve({ id: 1, links: { comments: "/posts/1/comments" } });
  };

  env.adapter.findHasMany = function(store, record, link, relationship) {
    equal(relationship.type, Comment, "findHasMany relationship type was Comment");
    equal(relationship.key, 'comments', "findHasMany relationship key was comments");
    equal(link, "/posts/1/comments", "findHasMany link was /posts/1/comments");

    return Ember.RSVP.resolve([
      { id: 1, body: "First" },
      { id: 2, body: "Second" }
    ]);
  };

  env.store.createRecord('post', {}).save().then(async(function(post) {
    return post.get('comments');
  })).then(async(function(comments) {
    equal(comments.get('isLoaded'), true, "comments are loaded");
    equal(comments.get('length'), 2, "comments have 2 length");
  }));
});

test("When a polymorphic hasMany relationship is accessed, the adapter's findMany method should not be called if all the records in the relationship are already loaded", function() {
  expect(1);

  env.adapter.findMany = function() {
    ok(false, "The adapter's find method should not be called");
  };

  env.store.push('user', { id: 1, messages: [ {id: 1, type: 'post'}, {id: 3, type: 'comment'} ] });
  env.store.push('post', { id: 1 });
  env.store.push('comment', { id: 3 });

  env.store.find('user', 1).then(async(function(user) {
    var messages = user.get('messages');
    equal(messages.get('length'), 2, "The messages are correctly loaded");
  }));
});

test("When a polymorphic hasMany relationship is accessed, the store can call multiple adapters' findMany method if the records are not loaded", function() {
  User.reopen({
    messages: hasMany('message', { polymorphic: true, async: true })
  });

  env.adapter.findMany = function(store, type) {
    if (type === Post) {
      return Ember.RSVP.resolve([{ id: 1 }]);
    } else if (type === Comment) {
      return Ember.RSVP.resolve([{ id: 3 }]);
    }
  };

  env.store.push('user', { id: 1, messages: [ {id: 1, type: 'post'}, {id: 3, type: 'comment'} ] });

  env.store.find('user', 1).then(async(function(user) {
    return user.get('messages');
  })).then(async(function(messages) {
    equal(messages.get('length'), 2, "The messages are correctly loaded");
  }));
});

test("Type can be inferred from the key of a hasMany relationship", function() {
  expect(1);
  env.store.push('user', { id: 1, contacts: [ 1 ] });
  env.store.push('contact', { id: 1 });
  env.store.find('user', 1).then(async(function(user) {
    return user.get('contacts');
  })).then(async(function(contacts) {
    equal(contacts.get('length'), 1, "The contacts relationship is correctly set up");
  }));
});

test("Type can be inferred from the key of an async hasMany relationship", function() {
  User.reopen({
    contacts: DS.hasMany({ async: true })
  });

  expect(1);
  env.store.push('user', { id: 1, contacts: [ 1 ] });
  env.store.push('contact', { id: 1 });
  env.store.find('user', 1).then(async(function(user) {
    return user.get('contacts');
  })).then(async(function(contacts) {
    equal(contacts.get('length'), 1, "The contacts relationship is correctly set up");
  }));
});

test("Polymorphic relationships work with a hasMany whose type is inferred", function() {
  User.reopen({
    contacts: DS.hasMany({ polymorphic: true })
  });

  expect(1);
  env.store.push('user', { id: 1, contacts: [ { id: 1, type: 'email' }, { id: 2, type: 'phone' } ] });
  env.store.push('email', { id: 1 });
  env.store.push('phone', { id: 2 });
  env.store.find('user', 1).then(async(function(user) {
    return user.get('contacts');
  })).then(async(function(contacts) {
    equal(contacts.get('length'), 2, "The contacts relationship is correctly set up");
  }));
});

test("A record can't be created from a polymorphic hasMany relationship", function() {
  env.store.push('user', { id: 1, messages: [] });

  env.store.find('user', 1).then(async(function(user) {
    return user.get('messages');
  })).then(async(function(messages) {
    expectAssertion(function() {
      messages.createRecord();
    }, /You cannot add 'message' records to this polymorphic relationship/);
  }));
});

test("Only records of the same type can be added to a monomorphic hasMany relationship", function() {
  expect(1);
  env.store.push('post', { id: 1, comments: [] });
  env.store.push('post', { id: 2 });

  Ember.RSVP.all([ env.store.find('post', 1), env.store.find('post', 2) ]).then(async(function(records) {
    expectAssertion(function() {
      records[0].get('comments').pushObject(records[1]);
    }, /You cannot add 'post' records to this relationship/);
  }));

});

test("Only records of the same base type can be added to a polymorphic hasMany relationship", function() {
  expect(2);
  env.store.push('user', { id: 1, messages: [] });
  env.store.push('user', { id: 2, messages: [] });
  env.store.push('post', { id: 1, comments: [] });
  env.store.push('comment', { id: 3 });

  var asyncRecords = Ember.RSVP.hash({
    user: env.store.find('user', 1),
    anotherUser: env.store.find('user', 2),
    post: env.store.find('post', 1),
    comment: env.store.find('comment', 3)
  });

  asyncRecords.then(async(function(records) {
    records.messages = records.user.get('messages');
    return Ember.RSVP.hash(records);
  })).then(async(function(records) {
    records.messages.pushObject(records.post);
    records.messages.pushObject(records.comment);
    equal(records.messages.get('length'), 2, "The messages are correctly added");

    expectAssertion(function() {
      records.messages.pushObject(records.anotherUser);
    }, /You cannot add 'user' records to this relationship/);
  }));
});

test("A record can be removed from a polymorphic association", function() {
  expect(3);

  env.store.push('user', { id: 1 , messages: [{id: 3, type: 'comment'}]});
  env.store.push('comment', { id: 3 });

  var asyncRecords = Ember.RSVP.hash({
    user: env.store.find('user', 1),
    comment: env.store.find('comment', 3)
  });

  asyncRecords.then(async(function(records) {
    records.messages = records.user.get('messages');
    return Ember.RSVP.hash(records);
  })).then(async(function(records) {
    equal(records.messages.get('length'), 1, "The user has 1 message");

    var removedObject = records.messages.popObject();

    equal(removedObject, records.comment, "The message is correctly removed");
    equal(records.messages.get('length'), 0, "The user does not have any messages");
  }));
});

test("When a record is created on the client, its hasMany arrays should be in a loaded state", function() {
  expect(3);

  var post;

  Ember.run(function() {
    post = env.store.createRecord('post');
  });

  ok(get(post, 'isLoaded'), "The post should have isLoaded flag");

  var comments = get(post, 'comments');

  equal(get(comments, 'length'), 0, "The comments should be an empty array");

  ok(get(comments, 'isLoaded'), "The comments should have isLoaded flag");

});

test("When a record is created on the client, its async hasMany arrays should be in a loaded state", function() {
  expect(4);

  Post.reopen({
    comments: DS.hasMany('comment', { async: true })
  });

  var post = Ember.run(function() {
    return env.store.createRecord('post');
  });

  ok(get(post, 'isLoaded'), "The post should have isLoaded flag");

  get(post, 'comments').then(function(comments) {
    ok(true, "Comments array successfully resolves");
    equal(get(comments, 'length'), 0, "The comments should be an empty array");
    ok(get(comments, 'isLoaded'), "The comments should have isLoaded flag");
  });

});

test("a records SYNC HM relationship property is readOnly", function(){
  expect(1);
  var post = Ember.run(function() {
    return env.store.createRecord('post');
  });

  raises(function(){
    post.set('comments');
  }, 'Cannot Set: comments on: ' + Ember.inspect(post));
});

test("a records ASYNC HM relationship property is readOnly", function(){
  expect(1);
  Post.reopen({
    comments: DS.hasMany('comment', { async: true })
  });

  var post = Ember.run(function() {
    return env.store.createRecord('post');
  });

  raises(function(){
    post.set('comments');
  }, 'Cannot Set: comments on: ' + Ember.inspect(post));
});

test("When a record is saved, its unsaved hasMany records should be kept", function () {
  expect(1);

  var post, comment;

  env.adapter.createRecord = function(store, type, record) {
    return Ember.RSVP.resolve({ id: 1 });
  };

  Ember.run(function () {
    post = env.store.createRecord('post');
    comment = env.store.createRecord('comment');
    post.get('comments').pushObject(comment);
    post.save();
  });

  equal(get(post, 'comments.length'), 1, "The unsaved comment should be in the post's comments array");
});
<|endoftext|>


<commit_before>// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('karma-junit-reporter'),
      require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    junitReporter: {
      outputDir: require('path').join(__dirname, '../output'),
      outputFile: 'junit.xml',
      useBrowserName: false
    },
    coverageIstanbulReporter: {
      dir: require('path').join(__dirname, '../coverage'),
      reports: ['html', 'lcovonly', 'text-summary'],
      fixWebpackSourcePaths: true
    },
    reporters: ['progress', 'kjhtml', 'junit'],
    port: 9876,
    colors: true,
    //logLevel: config.LOG_INFO,
    logLevel: config.LOG_DEBUG,
    autoWatch: true,
    browsers: ['Chrome'],
    browserDisconnectTimeout: 10000,
    browserDisconnectTolerance: 3,
    browserNoActivityTimeout: 600000,
    customLaunchers: {
      ChromeHeadlessCI: {
        base: 'ChromeHeadless',
        flags: [
          '--disable-web-security',
          '--disable-gpu',
          '--no-sandbox'
        ]
      }
    },
    singleRun: false
  });
};<commit_msg>appveyor chrome headless timeout #7<commit_after>// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular-devkit/build-angular'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('karma-junit-reporter'),
      require('@angular-devkit/build-angular/plugins/karma')
    ],
    client: {
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    junitReporter: {
      outputDir: require('path').join(__dirname, '../output'),
      outputFile: 'junit.xml',
      useBrowserName: false
    },
    coverageIstanbulReporter: {
      dir: require('path').join(__dirname, '../coverage'),
      reports: ['html', 'lcovonly', 'text-summary'],
      fixWebpackSourcePaths: true
    },
    reporters: ['progress', 'kjhtml', 'junit'],
    port: 9876,
    colors: true,
    //logLevel: config.LOG_INFO,
    logLevel: config.LOG_DEBUG,
    autoWatch: true,
    browsers: ['Chrome'],
    browserDisconnectTimeout: 10000,
    browserDisconnectTolerance: 3,
    browserNoActivityTimeout: 600000,
    customLaunchers: {
      ChromeHeadlessCI: {
        base: 'ChromeHeadless',
        flags: [
          '--disable-web-security',
          '--disable-gpu',
          '--enable-logging=stderr',
          ' --v=1',
          '--no-sandbox'
        ]
      }
    },
    singleRun: false
  });
};<|endoftext|>


<commit_before>module.exports = {
  module: {
    rules: [
      {
        test: /-story\.js$/,
        loaders: [
          {
            loader: require.resolve('@storybook/addon-storysource/loader'),
            options: {
              prettierConfig: {
                bracketSpacing: true,
                parser: 'babylon',
                printWidth: 80,
                singleQuotes: true,
                trailingComma: 'es5',
              },
            },
          },
        ],
        enforce: 'pre',
      },
    ],
  },
};
<commit_msg>chore(icons-react): fix example prettier options<commit_after>module.exports = {
  module: {
    rules: [
      {
        test: /-story\.js$/,
        loaders: [
          {
            loader: require.resolve('@storybook/addon-storysource/loader'),
            options: {
              prettierConfig: {
                bracketSpacing: true,
                parser: 'babylon',
                printWidth: 80,
                singleQuote: true,
                trailingComma: 'es5',
              },
            },
          },
        ],
        enforce: 'pre',
      },
    ],
  },
};
<|endoftext|>


<commit_before>var soundChart = new TimeChart({range: [0, 180], title: 'Sound sensor'});
var lightChart = new TimeChart({range: [0, 1], title: 'Light sensor'});
var proximityChart = new TimeChart({range: [0, 255], title: 'Proximity sensor'});

var servo1Chart = new AngleChart({title: 'Servo 1'});
var servo2Chart = new AngleChart({title: 'Servo 2'});
var servo3Chart = new AngleChart({title: 'Servo 3'});

var switchChart = new SwitchChart({title: 'Switch'});

var robot = new HTML5Robot();
//var robot = new RobotMock();

robot.addSensorListener('sound', function(data) {
  soundChart.addValue(data.value);
});
robot.addSensorListener('light', function(data) {
  lightChart.addValue(data.value);
});
robot.addSensorListener('proximity', function(data) {
  proximityChart.addValue(data.value);
});

robot.addSensorListener('servo1', function(data) {
  servo1Chart.setAngle(data.value);
});
robot.addSensorListener('servo2', function(data) {
  servo2Chart.setAngle(data.value);
});
robot.addSensorListener('servo3', function(data) {
  servo3Chart.setAngle(data.value);
});

robot.addSensorListener('switch', function(data) {
  switchChart.setState(data.value);
});
<commit_msg>Changing light scale<commit_after>var soundChart = new TimeChart({range: [0, 180], title: 'Sound sensor'});
var lightChart = new TimeChart({range: [0, 65535], title: 'Light sensor'});
var proximityChart = new TimeChart({range: [0, 255], title: 'Proximity sensor'});

var servo1Chart = new AngleChart({title: 'Servo 1'});
var servo2Chart = new AngleChart({title: 'Servo 2'});
var servo3Chart = new AngleChart({title: 'Servo 3'});

var switchChart = new SwitchChart({title: 'Switch'});

var robot = new HTML5Robot();
//var robot = new RobotMock();

robot.addSensorListener('sound', function(data) {
  soundChart.addValue(data.value);
});
robot.addSensorListener('light', function(data) {
  lightChart.addValue(data.value);
});
robot.addSensorListener('proximity', function(data) {
  proximityChart.addValue(data.value);
});

robot.addSensorListener('servo1', function(data) {
  servo1Chart.setAngle(data.value);
});
robot.addSensorListener('servo2', function(data) {
  servo2Chart.setAngle(data.value);
});
robot.addSensorListener('servo3', function(data) {
  servo3Chart.setAngle(data.value);
});

robot.addSensorListener('switch', function(data) {
  switchChart.setState(data.value);
});
<|endoftext|>