text: /*global QUnit, sinon */
  sap.ui.define([
  	"sap/m/SelectionDetailsItem",
  	"sap/m/SelectionDetailsItemLine",
  	"sap/ui/core/Item",
  	"sap/m/library",
  	"sap/ui/core/Core"
  ], function(SelectionDetailsItem, SelectionDetailsItemLine, Item, library, oCore) {
  	"use strict";
  
  	// shortcut for sap.m.SelectionDetailsActionLevel
  	var SelectionDetailsActionLevel = library.SelectionDetailsActionLevel;
  
  	// shortcut for sap.m.ListType
  	var ListType = library.ListType;
  
  	QUnit.module("Default values", {
  		beforeEach: function() {
  			this.oItem = new SelectionDetailsItem();
  		},
  		afterEach: function() {
  			this.oItem.destroy();
  			this.oItem = null;
  		}
  	});
  
  	QUnit.test("Default value of property navigationEnabled", function(assert) {
  		assert.equal(this.oItem.getEnableNav(), false, "Default value is correct.");
  	});
  
  	QUnit.module("Function _getListItem and list item life cycle", {
  		beforeEach: function() {
  			this.oItem = new SelectionDetailsItem();
  		},
  		afterEach: function() {
  			if (this.oItem) {
  				this.oItem.destroy();
  			}
  			this.oItem = null;
  		}
  	});
  
  	QUnit.test("Creates new list item if it not yet exists", function(assert) {
  		//Arrange
  		this.oItem._oListItem = null;
  
  		//Act
  		this.oItem._getListItem();
  
  		//Assert
  		assert.ok(this.oItem._oListItem, "Function _getListItem creates a new list item.");
  	});
  
  	QUnit.test("List item is member of element", function(assert) {
  		//Arrange
  		var oListItem = this.oItem._getListItem();
  
  		//Assert
  		assert.deepEqual(this.oItem._oListItem, oListItem, "The correct list item has been added as local member.");
  	});
  
  	QUnit.test("List item is destroyed as well if element is destroyed", function(assert) {
  		//Arrange
  		var oListItem = this.oItem._getListItem(),
  			oSpy = sinon.spy(oListItem, "destroy");
  		//Act
  		this.oItem.destroy();
  		//Assert
  		assert.ok(oSpy.calledOnce, "ListItem is destroyed.");
  	});
  
  	QUnit.test("List item is destroyed with element", function(assert) {
  		//Arrange
  		var oListItem = this.oItem._getListItem();
  		sinon.spy(oListItem, "destroy");
  
  		//Act
  		this.oItem.destroy();
  
  		//Assert
  		assert.equal(oListItem.destroy.callCount, 1, "ListItem has been destroyed with element.");
  	});
  
  	QUnit.test("Press handler for ListItem results in event called on SelectionDetailsItem", function(assert) {
  		//Arrange
  		var oListItem = this.oItem._getListItem();
  		sinon.spy(this.oItem, "fireEvent");
  
  		//Act
  		oListItem.firePress();
  
  		//Assert
  		assert.deepEqual(this.oItem.fireEvent.getCalls()[0].args[0], "_navigate", "press event of ListItem results in navigate event on SelectionDetailsItem.");
  	});
  
  	QUnit.module("Rendering", {
  		beforeEach: function() {
  			this.oItem = new SelectionDetailsItem({
  				lines: [
  					new SelectionDetailsItemLine({
  						label: "My Label",
  						value: "100"
  					}),
  					new SelectionDetailsItemLine({
  						label: "Fancy line",
  						value: "200",
  						unit: "Brötchen"
  					}),
  					new SelectionDetailsItemLine({
  						label: "Boring label",
  						displayValue: "20 K"
  					})
  				],
  				actions: [
  					new Item({
  						key: "1",
  						text: "item action 1"
  					}), new Item({
  						key: "2",
  						text: "item action 2"
  					})
  				]
  			});
  			this.oListItem = this.oItem._getListItem();
  			this.oListItem.placeAt("qunit-fixture");
  			oCore.applyChanges();
  		},
  		afterEach: function() {
  			this.oListItem = null;
  			this.oItem.destroy();
  			this.oItem = null;
  		}
  	});
  
  	QUnit.test("Item rendering", function(assert) {
  		//Arrange
  		var $ListItem = this.oListItem.$();
  
  		//Assert
  		assert.ok($ListItem.length > 0, "A list item is rendered.");
  		assert.ok($ListItem.hasClass("sapMSDItem"), "The correct class has been rendered.");
  		assert.equal($ListItem.find(".sapMSDItemActions").length, 1, "The correct number of action containers has been rendered.");
  	});
  
  	QUnit.test("Line rendering", function(assert) {
  		//Arrange
  		var $ListItem = this.oListItem.$();
  
  		//Assert
  		assert.equal($ListItem.find(".sapMSDItemLine").length, 3, "The correct number of lines has been rendered.");
  		assert.equal($ListItem.find(".sapMSDItemLineLabel").length, 3, "The correct number of labels has been rendered.");
  		assert.equal($ListItem.find(".sapMSDItemLineValue").length, 3, "The correct number of values has been rendered.");
  		assert.equal($ListItem.find(".sapMSDItemLineBold").length, 1, "The correct number of bold values has been rendered.");
  		assert.equal($ListItem.find(".sapMSDItemLineUnit").length, 1, "The correct number of units has been rendered.");
  	});
  
  	QUnit.test("Action rendering", function(assert) {
  		//Arrange
  		var $ListItem = this.oListItem.$();
  
  		//Assert
  		assert.ok(this.oItem.getAggregation("_overflowToolbar"), "OverflowToolbar has been created");
  		assert.ok(this.oItem.getAggregation("_overflowToolbar").getContent().length, 3, "Toolbar spacer and two buttons have been created");
  		assert.equal($ListItem.find(".sapMSDItemActions").length, 1, "The action buttons toolbar has been rendered");
  	});
  
  	QUnit.test("Internal SelectionDetailsListItem has correct type property for enabled navigation", function(assert) {
  		//Arrange
  		this.oItem.setEnableNav(true);
  		var oSetPropertySpy = sinon.spy(this.oListItem, "setProperty");
  		this.oListItem.invalidate();
  
  		//Act
  		oCore.applyChanges();
  
  		//Assert
  		assert.equal(oSetPropertySpy.withArgs("type", ListType.Navigation, true).callCount, 1, "ListItem's type property has been correctly updated.");
  	});
  
  	QUnit.test("Internal SelectionDetailsListItem has correct type property for disabled navigation", function(assert) {
  		//Arrange
  		this.oItem.setEnableNav(false);
  		var oSetPropertySpy = sinon.spy(this.oListItem, "setProperty");
  		this.oListItem.invalidate();
  
  		//Act
  		oCore.applyChanges();
  
  		//Assert
  		assert.equal(oSetPropertySpy.withArgs("type", ListType.Inactive, true).callCount, 1, "ListItem's type property has been correctly updated.");
  	});
  
  	QUnit.module("Item interaction", {
  		beforeEach : function() {
  			this.oItem = new SelectionDetailsItem({
  				actions: [new Item("itemAction", {
  					text: "Action 1"
  				})]
  			});
  			this.oSelectionDetailsListItem = this.oItem._getListItem();
  			this.oSelectionDetailsListItem.placeAt("qunit-fixture");
  			oCore.applyChanges();
  		},
  		afterEach : function() {
  			this.oSelectionDetailsListItem.destroy();
  			this.oSelectionDetailsListItem = null;
  		}
  	});
  
  	QUnit.test("Press on the Action results in _ActionPress event", function(assert) {
  		// Arrange
  		var sActionTypeExpected = "_actionPress",
  			oActionExpected = this.oItem.getAggregation("actions")[0],
  			oButton = oCore.byId(this.oItem.getId() + "-action-0"),
  			oSpy = sinon.spy(SelectionDetailsItem.prototype, "fireEvent");
  		// Act
  		oButton.firePress();
  		//Assert
  		assert.deepEqual(oSpy.getCall(0).args[0], sActionTypeExpected, "The _actionPress event of SelectionDetailsItem has been triggered");
  		assert.deepEqual(oSpy.getCall(0).args[1].action, oActionExpected, "The _actionPress event contains correct 'action' parameter");
  		assert.deepEqual(oSpy.getCall(0).args[1].items[0], this.oItem, "The _actionPress event contains correct 'items' parameter");
  		assert.deepEqual(oSpy.getCall(0).args[1].level, SelectionDetailsActionLevel.Item, "The _actionPress event contains correct 'level' parameter");
  	});
  
  	QUnit.module("Item facade", {
  		beforeEach : function() {
  			this.oItem = new SelectionDetailsItem();
  		},
  		afterEach : function() {
  			this.oItem.destroy();
  			this.oItem = null;
  		}
  	});
  
  	QUnit.test("Facade is not returning the original instance", function(assert) {
  		// Act
  		var oFacade = this.oItem.getFacade();
  		//Assert
  		assert.notDeepEqual(this.oItem, oFacade, "Proxy object is returned.");
  	});
  
  	QUnit.test("Facade proxy object is buffered on instance level", function(assert) {
  		// Act
  		var oFacadeFirstCall = this.oItem.getFacade();
  		var oFacadeSecondCall = this.oItem.getFacade();
  		//Assert
  		assert.equal(oFacadeFirstCall, oFacadeSecondCall, "Same proxy object is returned");
  	});
  
  	QUnit.test("Facade methods exist", function(assert) {
  		// Act
  		var aFacadeMethods = this.oItem._aFacadeMethods;
  
  		//Assert
  		assert.ok(aFacadeMethods.indexOf("addCustomData") > -1, "Facade contains method 'addCustomData'");
  		assert.ok(aFacadeMethods.indexOf("getCustomData") > -1, "Facade contains method 'getCustomData'");
  		assert.ok(aFacadeMethods.indexOf("indexOfCustomData") > -1, "Facade contains method 'indexOfCustomData'");
  		assert.ok(aFacadeMethods.indexOf("insertCustomData") > -1, "Facade contains method 'insertCustomData'");
  		assert.ok(aFacadeMethods.indexOf("removeCustomData") > -1, "Facade contains method 'removeCustomData'");
  		assert.ok(aFacadeMethods.indexOf("removeAllCustomData") > -1, "Facade contains method 'removeAllCustomData'");
  		assert.ok(aFacadeMethods.indexOf("destroyCustomData") > -1, "Facade contains method 'destroyCustomData'");
  		assert.ok(aFacadeMethods.indexOf("data") > -1, "Facade contains method 'data'");
  		assert.ok(aFacadeMethods.indexOf("addEventDelegate") > -1, "Facade contains method 'addEventDelegate'");
  		assert.ok(aFacadeMethods.indexOf("removeEventDelegate") > -1, "Facade contains method 'removeEventDelegate'");
  		assert.ok(aFacadeMethods.indexOf("setEnableNav") > -1, "Facade contains method 'setEnableNav'");
  		assert.ok(aFacadeMethods.indexOf("getEnableNav") > -1, "Facade contains method 'getEnableNav'");
  		assert.ok(aFacadeMethods.indexOf("addAction") > -1, "Facade contains method 'addAction'");
  		assert.ok(aFacadeMethods.indexOf("removeAction") > -1, "Facade contains method 'removeAction'");
  	});
  
  });